JAVA/JAVA2

[java2] #17 - Collection Framework(Set/List/Map), Iterator

yoonddo 2022. 7. 26. 21:06

컬렉션 프레임 워크

컬렉션 프레임 워크란 데이터를 저장하는 클래스들을 표준화 한 설계이며

아래 그림과 같이 데이터를 저장하는 구조에 따라 3가지 인터페이스로 구성된다.

 

Set, List, Map은 데이터들의 집합체라고 볼 수 있다. 그 중 Set과 List는 데이터의 그룹(Collection)이다.

Set 순서를 유지하지 않는 데이터의 집합이다.
데이터의 중복이 허용되지 않고 HashSet, TreeSet등이 있다.
List 순서를 유지하는 데이터의 집합이다.
데이터의 중복이 허용되며 Vector, LinkedList, ArrayList 등이 있다.
Map 키(Key)와 값(Value)으로 이루어진 데이터의 집합이다.
순서는 유지되지 않으며 키는 중복을 허용하지 않는다.

Map의 클래스로는 TreeMap, Hashtable, HashMap 등이 있다.

 


Collection

모든 컬렉션의 상위 인터페이스이다.

 

1. List

순서가 있고 중복을 허용한다.

index를 사용해 특정위치에 원소를 삽입하거나 접근할 수 있다.

크기가 가변적이다.

 

종류와 특징

ArrayList 이전 블로그 참고
https://yoonddo.tistory.com/24

- 단방향 포인터 구조로 데이터 순차적 접근에 강점을 가진다.
- 배열을 기반으로 데이터를 저장한다.
- 데이터 삽입, 삭제가 느리지만 데이터 검색이 빠르다.
Vector - ArrayList에 동기화가 보장되도록 최적화한 클래스이다.
- 모든 메소드가 동기화 되어있어서 잘 사용하지 않는다.
LinkedList - 노드, 링크로 구성된다.
- 양방향 포인터 구조로 데이터의 삽입, 삭제가 빈번할 경우 빠른 성능을 보장한다.
  삽입, 삭제 : O(1) / 검색 : O(n)
- ArrayList보다 검색이 느리다.
- 이름처럼 데이터를 담고있는 노드들이 연결되어 있는데, 노드의 포인터가
  다음이나 이전노드와의 연결을 담당한다.
- 스택, 큐, 양방향큐(덱) 등을 만들기 위한 용도로 사용한다.

2. Set

데이터의 집합이며 순서가 상관없고 요소의 중복을 허용하지 않는다.

중복되지 않은 데이터를 구할 때 유용하며 빠른 검색속도를 가진다.

인덱스가 따로 존재하지 않기 때문에 iterator를 사용한다.

HashSet 이전 블로그 참고
https://yoonddo.tistory.com/26

- 인스턴스의 해시값을 기준으로 저장하기 때문에 순서를 보장하지 않는다.
- NULL 값을 허용한다.
- TreeSet보다 삽입, 삭제가 빠르다.
LinkedHashSet - HashSet 클래스를 상속받은 LinkedList이다.
- 데이터가 삽입된 순서대로 데이터를 관리한다.
TreeSet - 정렬O
- 정렬된 순서대로 보관하며 정렬방법을 지정할 수 있다.
- 이진탐색트리(Red-Black-Tree) 형태로 데이터를 저장한다.
- 데이터를 추가, 삭제하는 시간이 더 걸리지만 검색과 정렬이 더 뛰어나다.
- 기본적으로는 오름차순으로 데이터를 저장한다.

3. Map

key와 Value의 한쌍으로 이루어지는 데이터의 집합이다.

Key에 대한 중복이 없으며 순서를 보장하지 않는다.

뛰어난 검색 속도를 가지며 인덱스가 따로 존재하지 않아 iterator를 사용한다.

HashMap 이전 블로그 참고 https://yoonddo.tistory.com/25

- Ket에 대한 중복이 없으며 순서를 보장하지 않는다.
- Key와 Value값으로 Null을 허용한다.
- 동기화가 보장되지 않는다.
- 검색에 가장 뛰어난 성능을 가진다. 
HashTable - 동기화가 보장되어 병렬 프로그래밍이 가능하고 HashMap보다    처리속도가 느리다.
- Key와 Value값으로 NULL을 허용하지 않는다.
LinkedHashMap - 입력된 순서를 보장한다.
TreeMap - 이진 탐색 트리(Red-Black Tree)를 기반으로 키와 값을 저장한다.
- Key값을 기준으로 오름차순 정렬되고 빠른 검색이 가능하다.
- 저장 시 정렬을 하기 때문에 시간이 다소 오래 걸린다.

 


List와 Set의 검색 속도 차이

- List는 인덱스를 관리하지만 Set은 값만 관리하기 때문에 List보다 검색 시간이 더 빠르다 

package day06;

import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.IntStream;

public class SpeedTest {
	public static void main(String[] args) {
		final int SIZE = 10_000_000;
		final List<Integer> arrayList = new ArrayList<Integer>();
		final Set<Integer> hashSet = new HashSet<>();
		final int data = 9_000_000;
		
		//순차 병렬 집계연산
		IntStream.range(0, SIZE).forEach(value -> {
			arrayList.add(value);
			hashSet.add(value);
		});
		
		Instant start = Instant.now();
		arrayList.contains(data);
		Instant end = Instant.now();
		
		long elapsedTime = Duration.between(start, end).toMillis();
		System.out.println("array list search time : " + elapsedTime + "밀리초");
		
		start = Instant.now();
		hashSet.contains(data);
		end = Instant.now();
		
		elapsedTime = Duration.between(start, end).toMillis();
		System.out.println("hash set search time : " + elapsedTime + "밀리초");
	}
}

Iterator (반복자)

Iterator는 자바의 컬렉션 프레임워크에서 컬렉션에 저장되어있는 요소들을 읽어오는 방법을

표준화 한 것이다.  데이터 집합체를 다룰 때는 개별적인 클래스에 대해 데이터를 읽는 방법을

알아야 하기 때문에 각 컬렉션에 접근이 힘들어진다. Iterator를 쓰게 되면 어떤 컬렉션

이라도 동일한 방식으로 접근이 가능해 그 안에 있는 항목들에 접근할 수 있는 방법을 제공한다.(다형성)

특징
 - Vector<E>, ArrayList<E>, LinkedList<E>가 상속받는 인터페이스
 - Iterator()를 호출하면 Iterator 객체 반환
 - 자바의 컬렉션에 저장되어있는 요소들을 읽어오는 방법의 인터페이스, 즉       쉽게 컬렉션으로부터 정보를 얻어내는 인터페이스이다.

 


Iterator  Method

 - hasNext() - 다음 요소에 읽어 올 요소가 있는지 확인하는 메소드 있으면 true, 없으면 false를 반환한다.

 - next() - 실제로 Iterator가 가리키는 데이터 저장소에서 현재 위치를 순차적으로 하나씩 증가해

                  다음 요소를 가져온다.

 - remove() - next()로 읽어온 요소를 삭제한다.

 

*메소드 호출 순서는 hasNext() -> next() -> remove() 이다.

 

1. 사용 방법

 - Iterator 개체는 컬랙션 개체의 iterator() 메서드를 호출하여 얻어올 수 있다.

 - hasNext() 메서드로 이동이 가능한지 확인 후 next() 메서드로 해당 위치의 보관한 개체를 참조하여

   원하는 작업을 수행한다.

 

2. 장점과 단점

 - Iterator 개체를 사용하면 size() 메서드를 얻어와서 반복 처리하는 것보다 속도에서 불리하다.

   이는 Iterator 개체를 사용하는 부분이 있기 때문에 불가피한 사항이다. 하지만 컬렉션 종류에

   관계없이 일관성있게 프로그래밍 할 수 있다는 장점을 갖고있다.

 - 소스코드에 어떠한 컬렉션을 사용할지 정해지지 않았지만 컬렉션 내에 보관한 모든 내용을 출력하는

   등의 작업을 먼저 하길 원한다면 Iterator를 사용하는 것은 좋은 선택이다.


// 사용가능한 객체 예시
ArrayList arr = new ArrayList();

  Vector<> vec = new Vector<>();

 LinkedList<Member>  link = new LinkedList<Member>();

 Set<String> st     = new Set<>(String);

// Iterator 객체 얻기
Iterator it0 = arr.iterator();  //vector의 요소를 순차 검색할 객체

  Iterator<> it1 = vec.iterator<>();

  Iterator<Member> it2 = link.iterator<Member>();

  Iterator<String> it3 = st.iterator<String>();

 // while문으로 하나씩 객체 얻기

 while (it0.hasNext()){

    String st = (String)it0.next();

 }

 - hasNext() : 해당 iterator 객체에 값 존재 여부 (boolean)

 - next() : iterator 객체의 값 얻기


// for문을 통한 객체 얻기
for(Member mem : link){

    mem.get();

    mem.set();

    ...

 }
 for(String stOne : st){

    System.out.println(stOne);

    ...

 }

 - for문을 통해 객체를 얻을 때는 Iterator 객체가 아닌 Collection 객체를 사용한다.

 - for문이 만나면 자동으로 Collection 객체의 요소를 순차적으로 얻어온다.

 

 

 

 

 

 

 

 

 

 

 

 

참고 출처 : https://joy-baek.tistory.com/20