컬렉션 프레임워크 (Collection Framework)란?

 : 잘 정의된, 약속된 구조와 골격 , 인스턴스의 저장과 참조를 위해 잘 정의된, 클래스들의 구조 의미합니다.

 

컬렉션 프레임워크라는 이름이 사용되는 이유:

4가지의 자료형이 성격에 따라서 구현된 코드들이 자료형의 이름만 변경하더라도 수행되도록 체계화 되어 있기 때문입니다.

 

         Collect
                                     List                                      Set
ArryList LinkedList HashSet TreeSet

 

List

1. 데이터의 중복을 허용합니다. (데이터 = 인스턴스)

2. 데이터를 저장할 때 저장 순서를 유지하여 관리합니다.

3. ArryList / LinkedList List의 구조를 상속받는 구조이기 때문에 Set을 특징을 그대로 물려받습니다.

 

ArryList / LinkedList

 

공통점 :

- 데이터의 중복을 허용합니다.

- 데이터를 저장할 때 저장 순서를 유지하여 관리합니다.

 

차이점 :

 

ArryList / LinkedList 둘의 장점과 단점이 반대로 되어 있습니다.

 

○ ArrayList : 배열로 되어 있는List입니다.

 

단점 :

1. 처음에 잡은 배열의 값을 넘어가면 알아서 메모리를 늘려서 값을 저장합니다. 하지만 이 과정에서 많은 시간이 소용되기 때문에 데이터 저장이 잦은 프로젝트 안에서는 비효율 적일 수 있습니다.

2. 삭제에 기능을 구현할 때 내부의 알고리즘이 복잡하게 구현되어, 성능의 저하를 가져올 여지가 있습니다.

 

장점 :

1.인덱스를 통해서 저장되어 있는 값을 빠르게 읽어올 수 있습니다. (데이터 접근 용이함)

 

○ LinkedList

 

장점:

1.저장공간을 늘리는 과정이 간단합니다.

2.삭제 동작이 매우 간단합니다.

 

단점 :

1.저장한 데이터를 참조가 불편합니다.

 

 

1) ArrayList

ArrayList : 빈번한 참조를 할 때 사용합니다. 

public class IntroArrayList {
	public static void main(String[] args) { 
		
		Integer num1 = new Integer(10); 
		Integer num2 = new Integer(20);
		Integer num3 = new Integer(30);
		
		Integer[] num = new Integer[3];
		num[0] = new Integer(10);
		num[1] = new Integer(20);
		num[2] = new Integer(30);
		
	
		
		//5버전 이후 부터 Generic으로 사용
		ArrayList<Integer> instanceInteger  = new ArrayList<Integer>(); 
        // 저장할 set 을 Integer로 한정지었다. 
	
		// 데이터 저장
		instanceInteger.add(new Integer(10)); 
		instanceInteger.add(new Integer(20));
		instanceInteger.add(new Integer(30));
		
		// 데이터 참조 
		for(int i = 0; i < instanceInteger.size(); i++ ) {   
        //  instanceInteger.size() : 저장하고 있는 instance를 반환해준다. 
			System.out.println(instanceInteger.get(i));      
            // get을 통해서 출력 할 수 있는데 시작 숫자는 0이다. 
		}
        
        // 데이터 삭제
		
		instanceInteger.remove(2); 
        // 삭제와 동시에 안에 비여있는 공간에 뒤에 있는 내용을 땡겨준다. 

- 5 버전부터 Generic을 사용하여 자료형을 선언하도록 만들었습니다.

 

- 데이터 저장을 저장할 때. add를 통해서 값을 저장합니다.

ex) instanceInteger.add(new Integer(10)); -> instanceInteger.add(10); 생략해줘도 5 버전 이후 지원해주는 AutoBoxing/ AutoUnBoxing에 의해서 오류가 나지 않습니다.

 

- 저장된 데이터를 출력할 때. get(); 사용합니다.

 

- 저장된 데이터의 개수를 확인할 때. size(); 사용합니다. (length와 같은 기능)

 

- 저장된 데이터 삭제. remove(); 삭제된 빈 공간에 뒤의 값이 들어와 하나씩 당겨줍니다.

 

 

2) LinkedList

LinkedList: 빈번하게 추가 삭제를 할 때 사용한다. 

public class IntroLinkedList {
	public static void main(String[] args) { 
		
		Integer num1 = new Integer(10); 
		Integer num2 = new Integer(20);
		Integer num3 = new Integer(30);
		
		Integer[] num = new Integer[3];
		num[0] = new Integer(10);
		num[1] = new Integer(20);
		num[2] = new Integer(30);
		
		LinkedList<Integer> instanceInteger  = new LinkedList<Integer>(); 
	
		// 데이터 저장
		instanceInteger.add(new Integer(10)); 
		instanceInteger.add(new Integer(20));
		instanceInteger.add(new Integer(30));
		
		// 데이터 참조 
		for(int i = 0; i < instanceInteger.size(); i++ ) {  
			System.out.println(instanceInteger.get(i));      
		}
        
        // 데이터 삭제
		instanceInteger.remove(2); 

위의 ArrayList와 똑같은 코드에 자료형만 바꾼 코드입니다. error가 하나도 발생하지 않으면 똑같이 진행됩니다. 이것을 보고 완벽한 호환이라고 이야기하며, 컬렉션 프레임워크 ( Collection Framework ) 임을 명확하게 보여줍니다.

 

 

Set

  1. 데이터의 중복을 허용하지 않습니다. (데이터 = 인스턴스)

  2. 데이터를 저장할 때 저장 순서를 유지하여 관리하지 않습니다.

  3. HashSet / TreeSet Set의 구조를 상속받는 구조이기 때문에 Set을 특징을 그대로 물려받습니다.

- 저장할 때

1. 중복확인을 위해서 전체 검색합니다.

2. 순서를 유지하지 않고 정리합니다.

 

: 추가적인 기능을 수행하기 때문에 퍼포먼스가 떨어집니다.

 

● HashSet / TreeSet

 

공통점 :

- 데이터의 중복을 허용하지 않습니다.

- 데이터를 저장할 때 저장 순서를 유지하여 관리하지 않습니다.

 

 차이점:

- TreeSet : 정렬해서 보관합니다. (성능이 4가지 중 가장 좋지 않다.)

- HashSet : : 정렬까지는 하지 않게 보관하며, TreeSet 성능이 더 좋아서 비교적 더 많이 사용합니다.

 

3) HashSet

 

public class IntroHashSet { 
	public static void main(String[] args) {
		HashSet<String> set = new HashSet<String>();
		
		// 데이터 저장
		set.add("Frist"); 
		set.add("Second");
		set.add("Third");
		set.add("Fourth");
		set.add("Second"); 
		
		System.out.println(set.size()); // 개수 : 4 (중복 저장x)
		
		// 데이터 참조 
		Iterator<String> itr = set.iterator();  
        // iterator(); interface로 저장되어 있다. 
        //set에 담겨 있는 정보로 itr 을 반환해 주고 있는 것이다. 
		// emthod가 스스로 new 해준다. (ex = calendar) 
		
		while(itr.hasNext()){  
    		System.out.println(itr.next());	 
		} // hasNext(): 데이터가 있는지 확인 하고 있으면 true, 없으면 false 
          // 데이터의 위치까지 확인할 수 있다. 
          // next() 사용하여 읽어 온다.
		
		// 5번전 부터 제공되는 for : each 문으로 Iterator를 사용하는 것보다 
        // 간편하게 출력할 수 있게 제공해준다. 
		for(String e:set) { 
			System.out.println(e);
		}


// 데이터 참조
for(int i = 0; i < set.size(); i++ ) {
System.out.println(set.get(i));

error : 읽어오는 get() 을 지원해 주지 않습니다 list 는 저장한 순서대로 반환 하기 때문에 의미가 있지만 set은 저장한 순서를 유지 하지 않으므로 의미가 없기 때문에 자료형의 특성상 지원해주지 않습니다. .get(); 을 대신하여 Iterator을 사용합니다.

 

Iterator란?

- iterator 메소드가 반환하는 참조값의 인스턴스는 Iterator 인터페이스를 구현하고 있습니다.
- iterator 메소드가 반환한 참조 값의 인스턴스를 이용하면, 컬렉션 인스턴스에 저장된 인스턴스의 순차적 접근이 가능

  합니다.
- iterator 메소드의 반환형이 Iterator이니, 반환된 참조 값을 이용해서 Iterator에 선언된 함수들만 호출하면 됩니다.

 

 

HashSet 저장되기 이전에 검색이 되어지는데 검색은 Object 안에 equals method를 불러와서 검색합니다.  equals method는 참조변수의 주소값으로 같은지 다른지를 확인합니다. 하지만 set 은 검색의 기능은 중복을 확인하고 있기 성능이 좋지 않으므로 내용이 많아지면 너무 늦어 질 수 있어서 이를 해결하기 위한 알고리즘을 만들어서 문제를 해결해야한다. 이를 해결하기 위해서 hashcode와 equals를 override 해서 해시알고리즘을 만들어서 보다 적은 단계로 비교하도록 만들 수 있습니다. 다음 예시를 보여드리겠습니다.

 

예시)

class Num{
	int num;
		
	Num(int num){
		this.num = num;
	}

	@Override
	public String toString() { 
		return String.valueOf(num); 
        // valueOf(num); 입력되는 데이터를 큰 따옴표를 붙여서 문자화 해준다. 
	}

	@Override
	public int hashCode() {
		System.out.println("hashCode() 호출.");
		return num % 3; 
        // 3으로 나눠서 나온 값 (0,1,2) = 각각의 결과 값끼리만 비교되도록 만든다. 
	}

	@Override
	public boolean equals(Object obj) { 
		System.out.println("equals() 호출.");
		Num comp = (Num)obj;
		
		if(comp.num == num) {
			return true;
		}else {return false;}
	}	
}

public class HashSetEquals {
	public static void main(String[] args) {
		HashSet<Num> set = new HashSet<>(); 
        
		set.add(new Num(10));
		set.add(new Num(20));
		set.add(new Num(10));
		set.add(new Num(30));

- toString 을 overriding 하여 Num 에 넣는 값을 문자화 하여 그 값을 비교하도록 합니다.

 

- hashcode 를 overriding 하여 3으로 나눠서 같은 나머지를 가진 결과들끼리 비교하도록 합니다.

 

- equals 를 overriding 하여 입력된 값과 들어오는 값을 비교하도록 합니다.

 

 

4) TreeSet

class Person implements Comparable<Person>{ 
	String name; 
	int age;
	
	Person(String name, int age){
		this.name = name;
		this.age = age;
	}
	
	public void showData() {
		System.out.println("이름 : " + name);
		System.out.println("나이 : " + age);
	}

	@Override
	public int compareTo(Person o) {
		return  o.age- age;
		
	}
}
public class ComparablePerson {
	public static void main(String[] args) {
		TreeSet<Person> set = new TreeSet<Person>();
		
		set.add(new Person("홍길동", 21));
		set.add(new Person("이순신", 25));
		set.add(new Person("강감찬", 28));
		set.add(new Person("유관순", 23));
		set.add(new Person("안중근", 25));
		set.add(new Person("강감찬", 28));
		
		for(Person e :  set) {   
			e.showData();
		}

  implements Comparable<Person> Comarable을 받아서 compareTo를 ovrriding 받아 정렬할 기준을 명확하게 해줍니다. hash code와 equals method를 사용하지 않아도 정렬하면서 필터링을 하기 때문에 필요하지 않습니다.

 

HashMap <K, V> (keyword, value)

 

- 키(key)와 값(value)의 쌍으로 구성되는 요소를 다루는 컬렉션입니다.

- K는 키로 사용할 요소의 타입, V값으로 사용할 요소의 타입 지정합니다.

- 키와 값이 한 쌍으로 삽입합니다.

- 키는 해시맵에 삽입되는 위치 결정에 사용합니다.

- 값을 검색하기 위해서는 반드시 키 이용합니다.

 

public class IntroHashMap {
	public static void main(String[] args) {
		HashMap <String, String> map = new HashMap <String, String>();
		
        // 데이터 입력 (.put();)
		map.put("이름", "홍길동"); 
		map.put("주소", "서울시 종로구");  
		map.put("이메일", "abc@aaa.com"); 
		map.put("전화번호", "010-1111-1111"); 
		
		// 데이터 참조( get(); )
		System.out.println(map.get("이름"));   
		System.out.println(map.get("주소")); 
		System.out.println(map.get("이메일")); 
		System.out.println(map.get("전화번호")); 
		
		// 데이터 삭제 
		map.remove("주소"); // key 값을 이용해서 삭제. 
		
	    System.out.println(map.get("주소"));  // 주소 값이 삭제 되어 초기값인 null 출력 

 - add를 사용하지 않고  put을 사용하는 이유는 관리의 방법이 다르기 때문입니다 : .put(); data 저장.

 

- 직접적으로 어떤 data가 들어가있는지 직관적으로 볼 수 있어서 활발히 활용합니다.

 

map 의 데이터 오름차순, 내림차순으로 출력 )

public class IntroTreeMap {
	public static void main(String[] args) {
		TreeMap<Integer, String> map = new TreeMap<Integer, String> (); 
		
		// 데이터 저장
	    map.put(6, "data6");   
	    map.put(4, "data4");
	    map.put(5, "data5");
	    map.put(2, "data2");
	    map.put(1, "data1");
	    map.put(3, "data3");
	    // map.put(new Integer(6), "data6");  
        // 5버전 부터 AutoBoxing 에 의해서 편리한 형태로 사용 가능 
        
	    for(int i = 0; i <=6 ;i++) {
	    System.out.println(map.get(i));
	    }
	    
	    NavigableSet<Integer> navi = map.navigableKeySet();

	    // 데이터 출력
	    System.out.println("==== 오름차순 =====");
	    Iterator<Integer> itr =navi.iterator();  // 
	    
	    while(itr.hasNext()) {
	    	System.out.println(map.get(itr.next()));
	    }
	    
	    System.out.println("==== 내림차순 ====");
	    itr = navi.descendingIterator();
	    
	    while(itr.hasNext()) {
	    	System.out.println(map.get(itr.next()));	
	    }

 

 직접적으로 어떤 data가 들어가있는지 직관적으로 볼 수 있어서 활발히 활용된다.

 

'빅데이터 > JAVA' 카테고리의 다른 글

[JAVA] 스트림(Stream)  (0) 2020.05.20
[JAVA] Thread  (0) 2020.05.19
[JAVA] Generics  (0) 2020.05.17
[JAVA] Calendar 클래스, Date 클래스 , Random 클래스  (0) 2020.05.17
[JAVA] Wrapper 클래스  (0) 2020.05.17

+ Recent posts