본문 바로가기

웹개발 수업/JAVA

[Day +25]Collection / Map, Map계열 메소드, HashMap, Hashtable, TreeSet, TreeMap, Properties

210727 화

 

Collection 

 

1. Map 

1) Map 특징

-Key와 값(멘틀)으로 구성

-키와 값은 모두 객체이다

-키는 중복 저장을 허용하지 않고 값은 중복 저장이 가능하다

-구현 클래스로 HashMap, HashTable, LinkedHashMap, Properties, TreeMap이 있음

 

2) Map 계열 주요 메소드

(1) 객체 추가

(2) 객체 검색

(3) 객체 삭제

3) Map 계열 클래스

(1) HashMap(동기화 X)

-키 객체는 hashCode()와 equals()를 재정의해 동등 객체가 될 조건을 정해야 함

-키 타입은 hashCode와 equals()메소드가 재정의되어 있는 String타입을 주로 사용

 

(2) Hashtable(동기화 O)

-스레드 동기화가 된 상태이기 때문에, 복수의 스레드가 동시에 Hashtable에 접근해 객체를 추가, 삭제 하더라도 스레드에 안전 (Thread safe)

package com.kh.chap03_map.part01_hashMap.controller;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;

import com.kh.chap03_map.part01_hashMap.model.vo.Car;

public class HashMapTest {
/*
 * Map계열의 특징 : 키(key)와 값(value)으로 구성 되어 있으며 키와 값은 모두 객체
 * 				키는 중복 저장 불가(Set 방식), 값은 중복 저장 가능(List방식)
 * 				중복된 키를 가진 값이 추가될 경우 기존 값에 덮어쓰기 처리 됨
 * Map 계열의 종류 : HashMap, HashTable, LingkedHashMap, Properties, TreeMap
 * HashMap : key객체는 hashCode, equals를 재정의 해야됨(Set에서처럼 동등 객체 중복 제거를 위해)
 * 			주로 String을 키 타입으로 사용(이미 hashCode, equals가 오버라이딩 되어 있음)
 * HashTable : HashMap의 구버전, 동기화 지원
 * LinkedHashMap : HashMap을 상속 받아 구현 된 클래스로 저장 순서가 유지 된다는 차이점만 있음
 */
	public void doHashMap() {
		 HashMap<String, Car> hm = new HashMap<>();
		//제네릭스 선언..
		// HashMap hm = new HashMap();
		//만약 제네릭스 선언이 되어있지 않다면 리턴값이 불명확하게 나온다.. get관련
		
		
		 //List, Set 값 추가시  add()
		 //1. put(K key, V value) : 지정한 키와 값 객체를 맵에 저장
		 hm.put("소나타", new Car("현대", 13.3));
		 hm.put("k5", new Car("기아", 16.1));
		 hm.put("말리부", new Car("쉐보레", 15.3));
		 System.out.println(hm);
		 
//		 {말리부=Car [manufacturer=쉐보레, fuelEfficiency=15.3], 
//		소나타=Car [manufacturer=현대, fuelEfficiency=13.3], 
//		k5=Car [manufacturer=기아, fuelEfficiency=16.1]}
		 
		 
		 //다른 key에 동등 객체 입력 => 동등 객체도 key값이 다르면 저장 가능
		 hm.put("아반떼", new Car("현대", 13.3));
		 System.out.println(hm);
//		 {말리부=Car [manufacturer=쉐보레, fuelEfficiency=15.3], 
//		아반떼=Car [manufacturer=현대, fuelEfficiency=13.3], 
//		소나타=Car [manufacturer=현대, fuelEfficiency=13.3], 
//		k5=Car [manufacturer=기아, fuelEfficiency=16.1]}
		 
		 
		 //같은 key에 다른 객체 입력 => 같은 key를 입력하면 새롭게 입력한 객체롭 변경됨(덮어쓰기)
		 hm.put("말리부", new Car("쉐보레", 16.3));
		 System.out.println(hm);
//		 {말리부=Car [manufacturer=쉐보레, fuelEfficiency=16.3], 
//		아반떼=Car [manufacturer=현대, fuelEfficiency=13.3], 
//		소나타=Car [manufacturer=현대, fuelEfficiency=13.3], 
//		k5=Car [manufacturer=기아, fuelEfficiency=16.1]}

		 
		//2. get(K key) : 지정한 키의 값 객체 가져오기
		 Car c = hm.get("k5");
		 System.out.println(c);
		
		 //답 : Car [manufacturer=기아, fuelEfficiency=16.1]
		 
		 
		 //3. containsKey(Object key) : key가 있으면 true 반환
		 //   containsValue(Object value) : value가 있으면 true 반환
		System.out.println(hm.containsKey("말리부"));
		System.out.println(hm.containsValue(new Car("쉐보레", 16.3)));
		 
//		true
//		false => 왜 false가 나올까?
		//List계열에서 contains 메소드로 동등 객체 구분하려고 한다면
		//equals 메소드가 해당 클래스에 오버라이딩 되어 있었어야 함..
		
		//오버라이딩 후에는 true값 출력 됨~!
		
		
		//4. remove(K key) : 해당 키 값의 인스턴스 삭제
		hm.remove("아반떼");
		System.out.println(hm);
		
		//아반떼 삭제되었음
//		{말리부=Car [manufacturer=쉐보레, fuelEfficiency=16.3], 
//		소나타=Car [manufacturer=현대, fuelEfficiency=13.3], 
//		k5=Car [manufacturer=기아, fuelEfficiency=16.1]}
		
		
		//size(), clear(), isEmpty() => 동일한 사용법이므로 생략하게뜸ㅎㅎ
		
		
		System.out.println("===================================================");
		
		//Map에 엘리먼트 접근하기
		//1. values() : 모든 values를 Collection에 담아 반환
		System.out.println(hm.values());
		//Car [manufacturer=쉐보레, fuelEfficiency=16.3], 
		//Car [manufacturer=현대, fuelEfficiency=13.3], 
		//Car [manufacturer=기아, fuelEfficiency=16.1]]
		
		//Map은 Key, value를 pair로 저장하고 있기 때문에 iterator() 호출 불가
		//keySet(), entrySet()과 같은 메소드를 통해서 Set형태로 키 또는 엔트리 값을 얻어와서
		//iterator 호출해서 사용
		
		//2. keySet
		//2_1. keySet + Iterator
		Set<String>keySet = hm.keySet();
		//지금 set안에 key값이 들어가있다고 생각하면 됨
		Iterator<String> it = keySet.iterator();
		while(it.hasNext()) {
			String key = it.next();
			System.out.printf("키 : %s, 값 : %s\n", key, hm.get(key));
			
//			키 : 말리부, 값 : Car [manufacturer=쉐보레, fuelEfficiency=16.3]
//			키 : 소나타, 값 : Car [manufacturer=현대, fuelEfficiency=13.3]
//			키 : k5, 값 : Car [manufacturer=기아, fuelEfficiency=16.1]
			
		}
		System.out.println();
		//2_2. keySet + for each
		for(String key : hm.keySet()) {
			System.out.printf("키 : %s, 값 : %s\n", key, hm.get(key));
			
//		키 : 말리부, 값 : Car [manufacturer=쉐보레, fuelEfficiency=16.3]
//		키 : 소나타, 값 : Car [manufacturer=현대, fuelEfficiency=13.3]
//		키 : k5, 값 : Car [manufacturer=기아, fuelEfficiency=16.1]
		}
		System.out.println();
		
		
		//3. entrySet : 모든 entry 객체(key + value)를 set에 담아서 반환
		//3_1. entrySet + Iterator
		Set<Entry<String, Car>> entrySet = hm.entrySet();
		Iterator<Entry<String, Car>> it2 = entrySet.iterator();
		while(it2.hasNext()) {
			Entry<String, Car> entry = it2.next();
			System.out.printf("키 : %s, 값 : %s\n", entry.getKey(), entry.getValue());
		
//			키 : 말리부, 값 : Car [manufacturer=쉐보레, fuelEfficiency=16.3]
//			키 : 소나타, 값 : Car [manufacturer=현대, fuelEfficiency=13.3]
//			키 : k5, 값 : Car [manufacturer=기아, fuelEfficiency=16.1]
		}
		
		System.out.println();
		//3_2. entrySet + for each
		for(Entry<String, Car> entry : hm.entrySet()) {
			System.out.printf("키 : %s, 값 : %s\n", entry.getKey(), entry.getValue());
			
//			키 : 말리부, 값 : Car [manufacturer=쉐보레, fuelEfficiency=16.3]
//			키 : 소나타, 값 : Car [manufacturer=현대, fuelEfficiency=13.3]
//			키 : k5, 값 : Car [manufacturer=기아, fuelEfficiency=16.1]	
		
		}
		
	}

}

 

package com.kh.chap03_map.part01_hashMap.model.vo;

public class Car {
	
	private String manufacturer; //제조사
	private double fuelEfficiency; //연비

	public Car() {}

	public Car(String manufacturer, double fuelEfficiency) {
		super();
		this.manufacturer = manufacturer;
		this.fuelEfficiency = fuelEfficiency;
	}

	public String getmanufacturer() {
		return manufacturer;
	}

	public double getFuelEfficiency() {
		return fuelEfficiency;
	}

	public void setmanufacturer(String manufacturer) {
		this.manufacturer = manufacturer;
	}

	public void setFuelEfficiency(double fuelEfficiency) {
		this.fuelEfficiency = fuelEfficiency;
	}

	@Override
	public String toString() {
		return "Car [manufacturer=" + manufacturer + ", fuelEfficiency=" 
        + fuelEfficiency + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		long temp;
		temp = Double.doubleToLongBits(fuelEfficiency);
		result = prime * result + (int) (temp ^ (temp >>> 32));
		result = prime * result + ((manufacturer == null) ? 0 : manufacturer.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Car other = (Car) obj;
		if (Double.doubleToLongBits(fuelEfficiency) 
        != Double.doubleToLongBits(other.fuelEfficiency))
			return false;
		if (manufacturer == null) {
			if (other.manufacturer != null)
				return false;
		} else if (!manufacturer.equals(other.manufacturer))
			return false;
		return true;
	}
}
package com.kh.chap03_map.part01_hashMap.run;

import com.kh.chap03_map.part01_hashMap.controller.HashMapTest;

public class Run {

	public static void main(String[] args) {
		HashMapTest ht = new HashMapTest();
		ht.doHashMap();
	}

}

(3) TreeSet과 TreeMap

: 검색 기능을 강화시킨 컬렉션으로, 계층 구조를 활용해 이진 트리 자료구조를 구현하여 제공

package com.kh.chap03_map.part02_treeMap.controller;

import java.util.Iterator;
import java.util.Set;
import java.util.TreeMap;
import java.util.Map.Entry;

import com.kh.chap03_map.part02_treeMap.model.comparator.DescString;
import com.kh.chap03_map.part02_treeMap.model.vo.Car;

public class TreeMapTest {

	public void doTreeMap() {
		
		//트리 구조로 정렬 기준을 가지고 저장할 경우 사용
		TreeMap<String, Car> tm = new TreeMap<String, Car>();
		
		//1. put(K key, V value) : 지정한 키와 값 객체를 맵에 저장
		tm.put("소나타", new Car("현대", 13.3));
		 tm.put("k5", new Car("기아", 16.1));
		 tm.put("말리부", new Car("쉐보레", 15.3));
		 System.out.println(tm);
		 
		 //아까와 저장 순서가 다르다. 
		 //Key값인 String클래스에 오버라이딩 된 compareTo 기준으로
		 //문자열 오름차순으로 정렬되어 있다.		
//		 {k5=Car [manufacturer=기아, fuelEfficiency=16.1], 
//		말리부=Car [manufacturer=쉐보레, fuelEfficiency=15.3], 
//		소나타=Car [manufacturer=현대, fuelEfficiency=13.3]}

		 //다른 key에 동등 객체 입력
		 //=> 동등 객체도 key값이 다르면 저장 가능
		 tm.put("아반떼", new Car("현대", 13.3));
		 System.out.println(tm);
//		 {k5=Car [manufacturer=기아, fuelEfficiency=16.1], 
//		말리부=Car [manufacturer=쉐보레, fuelEfficiency=15.3],
//		소나타=Car [manufacturer=현대, fuelEfficiency=13.3], 
//		아반떼=Car [manufacturer=현대, fuelEfficiency=13.3]}
		 
		 
		 //같은 key에 다른 객체 입력
		 // => 같은 key를 입력하면 새롭게 입력한 객체로 변경됨(덮어쓰기)
		 tm.put("말리부", new Car("쉐보레", 15.3));
		 System.out.println(tm);
//		 {k5=Car [manufacturer=기아, fuelEfficiency=16.1], 
//		말리부=Car [manufacturer=쉐보레, fuelEfficiency=15.3], 
//		소나타=Car [manufacturer=현대, fuelEfficiency=13.3], 
//		아반떼=Car [manufacturer=현대, fuelEfficiency=13.3]}
		 
		 System.out.println();
		 //2. 내림차순 구현 방법
		 //(1) 사용자 정의 클래스가 정렬 기준인 경우 Comparable 상속 받는 compareTo 변경
		 //(2) 매개변수 생성자를 통해 재정렬(Wrapper, String 클래스 등)
		 
		 TreeMap<String, Car> descTm = new TreeMap<>(new DescString());
		 
		 //1. put(K key, V value) : 지정한 키와 값 객체를 맵에 저장
		 descTm.put("소나타", new Car("현대", 13.3));
		 descTm.put("k5", new Car("기아", 16.1));
		 descTm.put("말리부", new Car("쉐보레", 15.3));
		 System.out.println(descTm);
		 
//		 {소나타=Car [manufacturer=현대, fuelEfficiency=13.3], 
//		말리부=Car [manufacturer=쉐보레, fuelEfficiency=15.3], 
//		k5=Car [manufacturer=기아, fuelEfficiency=16.1]}
		 
		 //복사하지 않고 직접 keySet, entrySet 이용한 순차 출력 연습하기
		 //tm, descTm
		 
		 System.out.println();
		 
		//2. keySet
		//2_1. keySet + Iterator
		 Set<String> ks = tm.keySet();
			//지금 set안에 key값이 들어가있다고 생각하면 됨
			Iterator<String> ksit = ks.iterator();
			while(ksit.hasNext()) {
				String key = ksit.next();
				System.out.printf("키 : %s, 값 : %s\n", key, tm.get(key));
				
//				키 : 말리부, 값 : Car [manufacturer=쉐보레, fuelEfficiency=16.3]
//				키 : 소나타, 값 : Car [manufacturer=현대, fuelEfficiency=13.3]
//				키 : k5, 값 : Car [manufacturer=기아, fuelEfficiency=16.1]
				
			}
			System.out.println();
			//2_2. keySet + for each
			for(String key : tm.keySet()) {
				System.out.printf("키 : %s, 값 : %s\n", key, tm.get(key));
				
//			키 : 말리부, 값 : Car [manufacturer=쉐보레, fuelEfficiency=16.3]
//			키 : 소나타, 값 : Car [manufacturer=현대, fuelEfficiency=13.3]
//			키 : k5, 값 : Car [manufacturer=기아, fuelEfficiency=16.1]
			}
			System.out.println();
			
			
			//3. entrySet : 모든 entry 객체(key + value)를 set에 담아서 반환
			//3_1. entrySet + Iterator
			Set<Entry<String, Car>> es = tm.entrySet();
			Iterator<Entry<String, Car>> esit = es.iterator();
			while(esit.hasNext()) {
				Entry<String, Car> entry = esit.next();
				System.out.printf("키 : %s, 값 : %s\n", entry.getKey(), entry.getValue());
			
//				키 : 말리부, 값 : Car [manufacturer=쉐보레, fuelEfficiency=16.3]
//				키 : 소나타, 값 : Car [manufacturer=현대, fuelEfficiency=13.3]
//				키 : k5, 값 : Car [manufacturer=기아, fuelEfficiency=16.1]
			}
			
			System.out.println();
			//3_2. entrySet + for each
			for(Entry<String, Car> entry : tm.entrySet()) {
				System.out.printf("키 : %s, 값 : %s\n", entry.getKey(), entry.getValue());
				
//				키 : 말리부, 값 : Car [manufacturer=쉐보레, fuelEfficiency=16.3]
//				키 : 소나타, 값 : Car [manufacturer=현대, fuelEfficiency=13.3]
//				키 : k5, 값 : Car [manufacturer=기아, fuelEfficiency=16.1]	
			
			}
	}

}
package com.kh.chap03_map.part02_treeMap.model.comparator;

import java.util.Comparator;

public class DescString implements Comparator<String> {

	@Override
	public int compare(String o1, String o2) {
		return o2.compareTo(o1);
	}

}
package com.kh.chap03_map.part02_treeMap.model.vo;

public class Car {
		
		private String manufacturer; //제조사
		private double fuelEfficiency; //연비

		public Car() {}

		public Car(String manufacturer, double fuelEfficiency) {
			super();
			this.manufacturer = manufacturer;
			this.fuelEfficiency = fuelEfficiency;
		}

		public String getmanufacturer() {
			return manufacturer;
		}

		public double getFuelEfficiency() {
			return fuelEfficiency;
		}

		public void setmanufacturer(String manufacturer) {
			this.manufacturer = manufacturer;
		}

		public void setFuelEfficiency(double fuelEfficiency) {
			this.fuelEfficiency = fuelEfficiency;
		}

		@Override
		public String toString() {
			return "Car [manufacturer=" + manufacturer + ", fuelEfficiency=" 
            + fuelEfficiency + "]";
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			long temp;
			temp = Double.doubleToLongBits(fuelEfficiency);
			result = prime * result + (int) (temp ^ (temp >>> 32));
			result = prime * result + ((manufacturer == null) 
            ? 0 : manufacturer.hashCode());
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			Car other = (Car) obj;
			if (Double.doubleToLongBits(fuelEfficiency) 
            != Double.doubleToLongBits(other.fuelEfficiency))
				return false;
			if (manufacturer == null) {
				if (other.manufacturer != null)
					return false;
			} else if (!manufacturer.equals(other.manufacturer))
				return false;
			return true;
		}
	}
package com.kh.chap03_map.part02_treeMap.run;

import com.kh.chap03_map.part02_treeMap.controller.TreeMapTest;

public class Run {

	public static void main(String[] args) {
		
		TreeMapTest tt = new TreeMapTest();
		tt.doTreeMap();
		

	}

}

1> 정렬(오름차순이 기본)

-TreeSet의 객체와 TreeMap의 key는 저장과 동시에 자동 오름차순 정렬

-숫자(Integer, Double) 타입일 경우 값으로 정렬

-문자열(String) 타입일 경우 유니코드로 정렬

-정렬을 위해 java.lang.Comparable을 구현한 객체 요구. 그러지 않을 경우 ClassCastException 발생

(Integer, Double, String 모두 Comparable 인터페이스를 통해 오름차순이 구현되어 있음)

 

2> 내림차순을 하고 싶다면? => 따로 구현해야 함

<1> TreeSet, TreeMap 객체 생성 시 매개변수 생성자를 통해 재정렬 가능

ex) TreeSet tSet = new TreeSet(Comparator comparator); TreeMap tMap = new TreeMap(Comparator comparator); 

<2> 숫자(Integer, Double), 문자열(String) 타입을 제외한 Comparable을 상속 받는 객체인 경우 compareTo() 메소드의 오버라이딩 부분을 내림차순으로 변경

 

(4) Properties

-키와 값을 String타입으로 제한한 Map컬렉션

-주로 Properties는 프로퍼티(*.properties)파일을 읽어 들일 때 주로 사용

 

1> 프로퍼티 파일 특징

- 옵션정보, 데이터베이스 연결정보, 국제화(다국어)정보를 기록하여 텍스트 파일로 활용

- 애플리케이션에서 주로 변경이 잦은 문자열을 저장하여 관리하기 때문에 유지보수를 편리하게 만들어 줌

- 키와 값이 ‘=‘기호로 연결되어 있는 텍스트 파일로 ISO 8859-1 문자셋으로 저장되고, 한글은 유니코드(Unicode)로 변환되어 저장

package com.kh.chap03_map.part03_properties.run;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

import com.kh.chap03_map.part02_treeMap.model.vo.Car;

public class PropertiesTest1 {

	public static void main(String[] args) {
		
		Properties prop = new Properties();
		
		//Properties : Map 계열
		//원래는 key, value 모두 String 타입만 사용
		/*prop.put("소나타", new Car("현대", 13.3));
		System.out.println(prop.get("소나타"));
		System.out.println(prop);
		
//		Car [manufacturer=현대, fuelEfficiency=13.3]
//		{소나타=Car [manufacturer=현대, fuelEfficiency=13.3]}
		
		
		//properties 파일로 저장
		try {
			prop.store(new FileOutputStream("car.properties"), "car");
		}  catch (IOException e) {
			e.printStackTrace();
		} 
		//Car cannot be cast to java.lang.String => 오류 발생 
		//위의  value에 숫자를 넣었기 때문
		 * 
		 */
		
		//1. setProperty(String key, String value) : 값 저장
		prop.setProperty("List", "ArrayList");
		prop.setProperty("Set", "HashSet");
		prop.setProperty("Map", "HashMap");
		prop.setProperty("Map", "Propeties");
		System.out.println(prop);
		//답 : {Map=Properies, List=ArrayList, Set=HashSet}
		
		//=> 저장 순서 유지 되지 않으며 키 중복 불가함. 중복 된 키의 경우 값 덮어쓰기.
		
		
		//2. getProperty(String key) : 값 얻어오기
		System.out.println(prop.getProperty("List"));
		
		
		//3. store(OutputStream os, String comments)
		// : 저장 된 정보를 바이트 스트림으로 파일에 출력 저장
		//	store(Writer writer, String comments)
		// : 저장 된 정보를 문자 스트림으로 파일에 출력 저장
		//	storeToXML(OutputStream os, String comments)
		// : 저장 된 정보를 바이트 스트림으로 XML파일에 출력 저장
		try {
			prop.store(new FileOutputStream("test.properties"), "test");
			
			//text파일이 생김
//			#test
//			#Tue Jul 27 17:59:51 KST 2021
//			Map=Propeties
//			List=ArrayList
//			Set=HashSet
			
			prop.storeToXML(new FileOutputStream("test.xml"), "test");
			//xml파일이 생김
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		

		



	}

}
package com.kh.chap03_map.part03_properties.run;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

public class PropertiesTest2 {

	public static void main(String[] args) {
		
		Properties prop = new Properties();
		//4. load(InputStream inStream)
		// : 바이트 스트림으로 저장된 파일의 내용을 읽어와서 Properties 객체에 저장
		// load(Reader reader)
		// : 문자 스트림으로 저장 도니 파일의 내용을 읽어와서 Properties 객체에 저장
		// loadFromXML(InputStream inStream)
		// : 바이트 스트림으로 저장 된 XML 파일의 내용을 읽어와서 Properties 객체에 저장
		
		try {
			//prop.load(new FileInputStream("test.properties"));
//			-- listing properties --
//			Map=Propeties
//			List=ArrayList
//			Set=HashSet
			
			prop.load(new FileInputStream("test.xml"));
//			-- listing properties --
//			<!DOCTYPE=properties SYSTEM "http://java.sun.co...
//			<properties>=
//			<entry=key="Set">HashSet</entry>
//			<comment>test</comment>=
//			<?xml=version="1.0" encoding="UTF-8" standa...
//			</properties>=

		} catch (IOException e) {
			e.printStackTrace();
		}
		
		
		//5. list(PrintStream out) : 특정 out stream을 통한 출력
		//System.out : 표준 출력 장치로 출력
		prop.list(System.out);
	}
	
	/*
	 * Properties 파일을 사용하는 이유?
	 * => key와 value가 모두 문자열로 제한되어 파일로 저장하고 읽어들이기 쉬움
	 * => 프로그램에서 변경되는 설정 정보들을 코드안에 작성하지 앟고 별도의 파일에서 관리하여
	 * 	  수정사항 발생 시 코드가 아닌 파일 내에서 수정할 수 있도록 함
	 * 
	 */
}

*ArrayList, HashMap중요