19.04.19 컬렉션 프레임워크

Back-End/Java 2019. 4. 19. 16:47
728x90
반응형

-컬렉션 프레임 워크-

 

객체들을 효율적으로 추가, 삭제, 검색할 수 있도록 java.util 패키지에 컬렉션과 관련된 인터페이스와 클래스들을 포함시켜 놓은것을
컬렉션 프레임 워크라고 한다.
컬렉션 프레임 워크의 주요 인터페이스로는 List,Set,Map가 있다.

(배열을 사용하면 다수의 객체를 저장하고 삭제했을 때 해당 인덱스가 비게되고, 새로운 객체를 저장하려면 어디가 비어 있는지
확인하는 코드도 필요하기 때문이다)

  
 
-List 컬렉션-

 

객체를 인덱스로 관리하기 때문에 객체를 저장하면 자동 인덱스가 부여되고 인덱스로 객체를 검색, 삭제할 수 있는 기능을 제공한다.
List 컬렉션은 객체 자체를 저장하는 것이 아니라 객체의 번지를 참조 한다.

 

 

-ArrayList-

 

일반 배열과 ArrayList는 인덱스로 객체를 관리한다는 점에서는 유사하지만, 배열은 생성할 때 크기가 고정되고 사용 중에 크기를 변경할 수 없지만,
ArrayList는 저장용량(capacity)을 초과한 객체들이 들어오면 자동적으로 저장용량이 늘어난다.
빈번한 객체 삽입과 삭제가 일어나는 곳에서는 ArrayList를 사용하는 것이 바람직하지 않다.
(ArrayList는 중간에 객체가 삭제되면 뒤에 있는 객체들이 전부다 한칸씩 앞으로 옮겨야 하는 등, 효율적이지 않기 때문이다.)

 

또한 size()는 컬렉션 타입의 길이를 확인할때 사용하고, length는 배열의 길이를 알려할때 사용한다.
즉 ArrayList에서는 length를 사용할 수 없다.

 

 

list<String> list = new ArrayList<String>();     //컬렉션 생성
list.add("홍길동");                             //컬렉션에 객체를 추가
String name = list.get(0);                     //컬렉션에서 객체 검색, 홍길동을 바로 얻음


고정된 객체들로 구성된 List를 생성할 때는 다음과 같이 사용한다.


List<T> list = Arrays.asList(T...a); //제네릭 사용

 

 

 

 

-예제 및 출력 결과-

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.hs.chap15;
 
import java.util.*// *은 util디렉토리 안에 있는 모든 클래스를 사용하겠다는 말입니다.
 
public class ArrayListExample {
 
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
 
        list.add("java"); // add는 객체를 저장한다.
        list.add("이한섭");
        list.add("5");
 
        int size = list.size(); // 저장된 총 객체수를 얻는다.
        System.out.println("배열에 저장된 총 객체수 : " + list.size()); // add로 넣은 list에 총 3개의 문자열이 있기 때문에 3이 출력된다.
 
        list.add(3"영창"); // 인덱스 번호 3번에 영창이라는 문자열을 추가한다.
 
        for (int i = 0; i < list.size(); i++) {
            System.out.println("배열에 저장되어 있는 값 : " + list.get(i));
        }
 
        System.out.println("2번째 인덱스에 저장되어 있는 값 : " + list.get(2));
 
        list.remove(1); // 1번 인덱스를 삭제
        list.remove(2); // 2번 인덱스를 삭제
 
        for (int i = 0; i < list.size(); i++) {
            System.out.println("1번과 2번 인덱스 삭제한 배열에 저장되어 있는 값 : " + list.get(i));
        }
    }
}
 
cs
   

 

 

 

-제네릭 타입 <E>-

 

타입파라미터라고 부른고,컴파일 할때 해당 타입이 일치하는지 확인할 수 있어,
좀 더 오류를 발생시키지 않고 안전하게 사용할 수 있게 하기 위해 사용한다.

 

 

 

-Vector-

 

ArrayList와 동일한 내부 구조를 가지고 있고, Vector를 생성하기 위해서는 저장할 객체 타입을 타입 파라미터로 표기하고
기본 생성자를 호출하면 된다.

ArrayList와 다른점은 동기화된(synchronized) 메소드로 구성되어 있기 때문에 멀티 스레드가 동시에 이 메소드들을 실행할수 없고,

하나의 스레드가 실행을 완료해야만 다른 스레드를 실행할 수 있다.

그렇기 때문에 멀티 스레드 환경에서 안전하게 객체를 추가, 삭제할 수 있다.

 

List<E> list = new Vector<E>();

 

 

 

-LinkedList-

 

LinkedList는 List 구현 클래스이므로 ArrayList와 사용방법은 같지만 내부구조는 다르다.
ArrayList는 내부 배열에 객체를 저장해서 인덱스로 관리하지만, LinkedList는 인접 참조를 링크해서
체인처럼 관리한다.

LinkedList를 생성하기 위해서는 저장할 객체 타입을 타입 파라미터(E)에 표기하고 기본 생성자를 호출하면 된다.
또한 처음 생성될때는 어떠한 링크도 만들어지지 않기 때문에 내부는 비어 있다고 보면 된다.

 

List<E> list = new LinkedList<E>();

 

 

 

-Set 컬렉션-

 

List 컬렉션은 저장 순서를 유지하지만, Set 컬렉션은 저장 순서가 유지되지 않는다.
또한 객체를 중복해서 저장할 수 없고, 하나의 null만 저장할 수 있다.
Set 컬렉션은 인덱스로 객체를 검색해서 가져오는 메소드(get())가 없다.

 

Iterator() 메소드 = 전체 객체를 대상으로 한번씩 반복해서 가져온다.

 

next() 메소드 = 하나의 객체를 가져올 때 사용.

 

hasNext() 메소드 = 가져올 객체가 있으면 true를 리턴하고, 더 이상 가져올 객체가 없으면 false를 리턴한다.

 

 

 

-HashSet-


HashSet는 객체를 저장하기 전에 먼저 hashCode()메소드를 호출해서 해시코드를 얻어낸다.
그리고 이미 저장되어 있는 객체들의 해시코드와 비교한다.
만약 동일한 해시코드가 있다면 다시 equals() 메소드로 두 객체를 비교한다.
true가 나오면 동일한 객체로 판단하고 중복저장을 하지 않는다.

 

 


-Map 컬렉션-

 

Map 컬렉션은 키(key)와 값(value)으로 구성된 Entry 객체를 저장하는 구조를 가지고 있다.
여기서 키와 값은 모두 객체이다.
키는 중복 저장될 수 없지만 값은 중복 저장될 수 있다.
만약 기존에 저장된 키와 동일한 키로 값을 저장하면 기존의 값은 없어지고 새로운 값으로 대치된다.

 

 

ex) HashMap<String, Integer> a = new HashMap<String, Integer>(); //키와 값을 받아야 하기 때문에 제네릭 타입을 <String, Integer> 두개를 설정

    a.put("one",1);  //키 값을 one, value 값을 1로 설정
    System.out.println(a.get("one")); //키(key)인 one를 호출하면 그 키의 값(value)인 1이 출력이 된다.

 

 

-예시-

 

Map 컬렉션은사우나의 물품보관함과 비슷한 개념을 가진다.
- 물품보관함의 번호는 순서대로 있지만 열쇠(키)가 없으면 물품을 보관을 할 수가 없다.
- 중복된 열쇠는 허용하지 않으며 물품은 중복이 가능해도 된다.
•위 처럼 열쇠(키)와 물품(값)으로 구성된 자료구조를 Map계열 컬렉션이라고 한다.
•Map계열에서 키는 유니크해야한다.

 

 

HashMap<Integer, String> hashMap = new HashMap<Integer, String>();
- HashMap컬렉션은 생성형태는 intger를 키로사용하고 String을 값으로 사용했다.

 

 

•hashMap.put(0, "str0");
- List계열과는 달리 put메소드를 이용해 데이터를 추가한다.

 

 

•hashMap.remove(2);
- 여기서 "2"는 키를 의미한다.
- 2번 키를 삭제한다.

 

 

•hashMap.clear();
- 컬렉션에 담은 키와 값을 전체 삭제한다.
- 아직은 메모리에 연결된 상태로 추가를 할 수 있다.

 

 

•Iterator<Integer> iterator = hashMap.keySet().iterator();
- Iterator 인터페이스는 반복적인 데이터를 검색하는데 유용하다.
- hashMap.keySet() 메소드를 이용해 반복적인 작업을 수행한다.

 

 

-예제 및 출력 결과-

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package com.hs.chap15;
 
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
 
public class HashMapExample {
    public static void main(String[] args) {
        // Map 컬렉션 생성
        Map<String, Integer> map = new HashMap<String, Integer>(); // 맵 컬렉션으로 키와 값을 받기 위해 키는 String, 값은 Integer 타입을
                                                                    // 선언한다.
 
        // 객체 저장
        map.put("신용권"85); // 키 와 값을 저장
        map.put("홍길동"90);
        map.put("동장군"80);
        map.put("홍길동"95); // "홍길동" 키가 같기 때문에 2번째 저장한 값은 마지막에 저장한 값으로 대치된다.
        System.out.println("총 Entry 수: " + map.size());
 
        // 객체 찾기
        System.out.println("/t홍길동 : " + map.get("홍길동")); // 홍길동 이라는 키로 값을 검색한다.
        System.out.println();
 
        // 객체를 하나씩 처리
        Set<String> keySet = map.keySet(); // 키를 얻는 keyset 메소드로 키를 얻어서 keyset에 저장한다.
        Iterator<String> keyIterator = keySet.iterator(); // 모든 키값을 불러와서 keyIterator에 저장
        while (keyIterator.hasNext()) // 키를 한개씩 불러온다.
        {
            String key = keyIterator.next();
            Integer value = map.get(key);
            System.out.println("/t" + key + ":" + value); // 키 4개중에 홍길동은 위에서 중복되었기 때문에 키가 3개만 출력이 된다.
        }
        System.out.println();
 
        // 객체 삭제
        map.remove("홍길동"); // 키 3개중에서 1개가 삭제되었기 때문에 2개가 남는다.
        System.out.println("총 Entry 수 : " + map.size()); // 남은 키는 2개이기 때문에 size()의 값은 2개가 된다.
 
        Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
        Iterator<Map.Entry<String, Integer>> entryIterator = entrySet.iterator();
 
        while (entryIterator.hasNext()) // 위에서 처럼 키를 얻어 저장된 값을 출력한다.
        {
            Map.Entry<String, Integer> entry = entryIterator.next();
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println("/t" + key + " : " + value); //남은 키는 2개이기 때문에 해당 키에 해당되는 값 2개가 출력이 된다.
        }
        System.out.println();
 
        // 객체 전체 삭제
        map.clear(); //남은 2개의 키가 삭제 되었기 때문에 남은 Entry의 수는 0개가 된다.
        System.out.println("총 Entry 수: " + map.size()); 
    }
}
 
cs

 

 

 

-Hashtable-

 

Hashtable는 HashMap와 동일한 내부 구조를 가지고 있다.

Hashtable도 키로 사용할 객체는 hashCode()와 equals() 메소드를 재정의해서 동등 객체가 될 조건을
정해야 한다.

 

HashMap과의 차이점은 Hashtable은 동기화된(synchronized) 메소드로 구성되어 있기 때문에
멀티 스레드가 동시에 이 메소드들을 실행할 수는 없고, 하나의 스레드가 실행을 완료해야만 다른
스레드를 실행할 수 있다.

 

형식 : Map<K, V> map = new Hashtable<K, V>( );

 

 

 

-Properties-

 

Properties는 Hashtable의 하위 클래스이기 때문에 Hashtable의 모든 특징을 그대로 가지고 있다.

차이점으로는 Hashtable는 키와 값을 다양한 타입으로 지정이 가능한데 비해 Properties는 키와 값을 String 타입으로

제한한 컬렉션이다.

주로 애플리케이션의 옵션 정보, 데이터베이스 연결 정보, 그리고 프로퍼티 파일을 읽을 때 주로 사용한다.

 

 

 

-이진 트리 구조-

 

여러개의 노드(node)가 트리 형태로 연결된 구조. 루트 노드라고 불리는 하나의 노드에서 시작해
각 노드에 최대 2개의 노드를 연결할 수 있는 구조를 가지고 있다.
위아래로 연결된 두 노드를 부모-자식관계에 있다고 하여 위의 노드를 부모 노드, 아래의 노드를
자식 노드라고 한다.
하나의 부모 노드는 최대 두 개의 자식 노드와 연결 될 수 있다.
또한 작은 값은 왼쪽에, 큰 값은 오른쪽에 저장한다.
숫자가 아닌 문자를 저장할 경우에는 문자의 유니코드 값으로 비교한다.

 

왼쪽 마지막 노드에서부터 오른쪽 마지막 노드까지[왼쪽 노드 -> 부모 노드 -> 오른쪽 노드]
순으로 읽으면 오름차순으로 정렬된 값을 얻을수 있고,

 

오른쪽 마지막 노드에서부터 왼쪽 마지막 노드까지[오른쪽 노드 -> 부모 노드 -> 왼쪽 노드]
순으로 읽으면 내림차순으로 정렬된 값을 얻을수 있다.

 

 

 

-TreeSet-

 

TreeSet는 이진트리를 기반으로한 Set 컬렉션이다. 하나의 노드는 노드값인 value와 왼쪽과 오른쪽 자식 노드를 참조하기 위한 두개의 변수로 구성된다.

부모값과 비교해서 낮은 것은 왼쪽 자식 노드에, 높은 것은 오른쪽 자식 노드에 저장한다.

 

TreeSet를 생성하기 위해서는 저장할 객체 타입을 파라미터로 표기하고 기본 생성자를 호출하면 된다.

TreeSet<E> treeSet = new TreeSet<E>( );

 

String 객체를 저장하는 TreeSet은 다음과 같이 생성할 수 있다.

TreeSet<String> treeSet = new TreeSet<String>( );

 

 

-예제 및 출력 결과-

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.hs.chap15;
 
import java.util.TreeSet;
 
public class TreeSetExample {
 
    public static void main(String[] args) {
        TreeSet<Integer> scores = new TreeSet<Integer>();
        scores.add(new Integer(87));
        scores.add(new Integer(98));
        scores.add(new Integer(75));
        scores.add(new Integer(95));
        scores.add(new Integer(80));
 
        Integer score = null;
 
        score = scores.first(); // TreeSet의 first()메소드는 가장 낮은 값을 리턴한다.
        System.out.println("가장 낮은 점수: " + score);
 
        score = scores.last(); // TreeSet의 first()메소드는 가장 낮은 값을 리턴한다.
        System.out.println("가장 큰 점수: " + score);
 
        score = scores.lower(new Integer(95)); // TreeSet의 lower()메소드는 매개값보다 낮은 객체를 리턴한다.
        System.out.println("95점 아래 점수: " + score);
 
        score = scores.higher(new Integer(95)); // TreeSet의 Integer()메소드는 매개값보다 큰 객체를 리턴한다.
        System.out.println("95점 위의 점수: " + score);
 
        score = scores.floor(new Integer(95)); // TreeSet의 floor()메소드는 매개값보다 작은 바로 아래 객체를 리턴한다.
        System.out.println("95점 이거나 바로 아래 점수: " + score);
 
        score = scores.ceiling(new Integer(85)); // TreeSet의 ceiling()메소드는 매개값보다 작은 바로 아래 객체를 리턴한다.
        System.out.println("85점 이거나 바로 위의 점수: " + score);
 
        while (!scores.isEmpty()) {
            score = scores.pollFirst();
            System.out.println(score + "(남은 객체 수: " + scores.size() + ")");
        }
    }
}
 
cs

 

 

 

 

 

-TreeMap-

 

TreeMap는 이진 트리를 기반으로 한 Map 컬렉션이다. TreeSet와의 차이점은 키와 값이 저장된 Map.Entry를 저장한다는 점이다.

기본적으로 부모 키 값과 비교해서 키 값이 낮은 것은 왼쪽 자식 노드에, 키 값이 높은 것은 오른쪽 자식 노드에 Map.Entry 객체를 저장한다.

 

TreeMap<K, V> treeMap = new TreeMap<K, V>( );    // K는 키 타입, V는 값 타입

 

 

 

-LIFO 와 FIFO-

 

후입선출(LIFO)은 나중에 넣은 객체가 먼저 빠져나가는 자료구조를 말한다.

선입선출(FIFO)은 먼저 넣은 객체가 먼저 빠져나가는 구조.

 

 

 

-Stack-

 

Stack 클래스는 LIFO 자료구조를 구현한 클래스이다.

 

Stack<E> stack = new Stack<E>( );

 

 

 

-Queus-

 

Queue 인터페이스는 FIFO 자료구조에서 사용되는 메소드를 정의하고 있다.

다음은 Queue 인터페이스에 정의되어 있는 메소드를 보여준다.

Quesu 인터페이스를 구현한 대표적인 클래스는 LinkedList이다.

LinkedList는 List 인터페이스를 구현했기 때문에 List 컬렉션이기도 하다.

 

Queue<E> queue = new LinkedList<E>( );


728x90
반응형

'Back-End > Java' 카테고리의 다른 글

19.04.21 IO 기반 입출력 및 네트워킹-1  (0) 2019.04.21
19.04.20 스트림과 병렬 처리  (0) 2019.04.20
19.04.18 람다식  (0) 2019.04.18
19.04.17 제네릭,와일드카드  (0) 2019.04.17
19.04.16 멀티 스레드  (0) 2019.04.16
: