Programing/JAVA

JAVA Collection Framework 정리, 자바 컬렉션, List, Set, Map, Queue Stream 1부 List

리커니 2018. 11. 12.
반응형

JAVA Collection Framework 정리, 자바 컬렉션, List, Set, Map, Queue, Stream 1부 List

 

자바에서는 데이터를 저장하기 위한 저장소로 배열과 컬렉션 프레임워크를 제공합니다.

그럼 배열이 있는데 왜 컬렉션 프레임워크가 나왔을 까요?

배열의 단점이 있으니 그랬겠죠?

 

배열은 생성할 때 미리 데이터의 크기를 알아야 합니다.

선언과 동시에 그 크기를 설정해야만 합니다.

String[] data = new String[];

 

위와 같이 선언을 하면 컴파일 오류가 발생하게 되죠.;

그렇기 떄문에 선언부터 데이터의 저장, 출력, 삭제, 수정 등에 매우 많은 신경을 써야 합니다.

 

이번 포스팅에서는 배열의 단점을 보완한 컬렉션 '프레임워크' 에 대해서 알아보도록 하겠습니다.

컬렉션 클래스가 아닌, 프레임워크라고 칭하는 이유는 그만큼 다양한 기능이 구현되어 있다는 의미 일 것입니다.

이 중 가장 많이 사용되는 기본 컬렉션과 그 컬렉션의 메소드 들에 대해 알아보도록 하겠습니다.

 

컬렉션을 사용할 때 가장 중요하게 알고 넘어가야 할 개념은

컬렉션은 값을 저장하는 것이 아니라, 메모리 주소(인스턴스) 만이 저장된다는 것 입니다.

 

1. List

 

List Collection 의 특징에는

① 배열과 같이 데이터의 저장 순서(Index) 가 존재

② 중복 데이터를 하용

한다는 점이 있습니다.

 

배열과 쓰임은 비슷하지만, 그 단점을 보완했습니다.

전체 데이터의 크기를 알지 못해도 선언이 가능하며, 데이터 삽입/삭제시 기존 데이터를 밀거나 당기는 Swap 처리를 자동으로 해주죠.

 

많이 사용하는 List 클래스에는 배열과 비슷한 ArrayList와 LinkedList 가 있습니다.

이 둘은 사용하는 용도가 다르기 때문에 특징을 잘 알고 사용하여야 합니다.

 

 

 

 

1) ArrayList

 ArrayList의 경우 배열과 같이 Index로 데티어를 찾기 때문에 검색속도가 빠릅니다.

하지만 데이터의 추가, 삭제 시 임시 배열을 생성해 데이터를 복사하는 로직을 사용하기 떄문에

그만큼 부하가 크죠.

데이터의 삽입 삭제가 없이 단순 검색만을 사용하는 로직에서 사용합니다.

 

2) LinkedList

 LinkedList의 경우 List의 특징은 유지하되, 데이터를 저장하는 노드가 이전노드와 다음 노드의 주소값만을 가지고 있습니다. 따라서 데이터의 추가 삭제시 그 노드의 주소값만을 수정하므로 ArrayList와 다르게 불필요한 데이터의 복사가 없어 부하가 적습니다. 하지만 데이터 검색 시 처음 노드부터 순회해야 하므로 검색에는 성능상 부하가 있습니다.

 

※ 데이터의 단순 검색 로직의 경우 ArrayList를, 삽입/삭제가 빈번히 일어나는 로직에서는 LinkedList를 사용합니다.

 

그럼 List Collection의 메소드에 대해서 알아보도록 하겠습니다.

 

Method Name Explanation
size 컬렉션에 저장된 데이터 개수 리턴
isEmpty 데이터가 비었으면 true 아니면 false
contains 데이터의 포함여부, 있으면 true 없으면 false
indexOf 해당 데이터의 index를 리턴, 없으면 -1
lastIndexOf 마지막 데이터의 index를 리턴, 없으면 -1, 마지막 index부터 검색
clone 해당 객체를 복사
toArray 객체를 배열로 리턴
get 해당 index의 데이터를 리턴
set 해당 index의 데이터를 수정
add 마지막 index에 데이터를 추가
remove 해당 index의 데이터를 삭제
clear 모든 데이터를 삭제
addAll 복수의 컬렉션을 합침
removeRange index 범위 내 데이터를 삭제
removeAll 해당 컬렉션에 해당하는 모든 데이터 삭제, 전체 삭제가 목적이면 clear 사용
retainAll 중복된 데이터만 유지, 나머지 삭제
listIterator Iterator를 상속받은 interface, list collection에서만 사용, iterator보다 다양한 기능 제공
Iterator 전체 컬렉션 요소에 접근할 때 사용. 반복문, for문이 속도는 빠르지만, 객체 삭제시에는 Iterator를 사용하지 않으면 Exception, 혹은 원치않는 데이터를 보게됨..
subList index 범위에 해당하는 리스트 객체를 리턴, from 이상 to 미만에 주의
forEach Java 1.5에 등장, for, iterator의 코드 단순화 등
spliterator Java 1.8에 등장. Collections와 Stream 패키지 둘 다 사용. 추가 메소드 제공
removeIf Java 1.8에 등장. Collections와 Stream 패키지 둘 다 사용. remove 코드의 단순화 등.
replaceAll List Collection 내 해당하는 모든 값을 변경할 때 사용
sort List 데이터를 정렬.

 

메소드 사용법과 자세한 설명은 아래의 Link를 참고하세요.

 

※참조

Link : https://docs.oracle.com/javase/8/docs/api/

 

※ Remove 시 주의사항

 

try{
    List<Integer> testArrayList = new ArrayList<Integer>();
    testArrayList.add(1);
    testArrayList.add(2);
    testArrayList.add(3);
    testArrayList.add(4);
    testArrayList.add(5);
            
    System.out.println(testArrayList);
    for (Integer value : testArrayList) {
        if (value==3) {
            testArrayList.remove(value);
        }
    }
    System.out.println(testArrayList);
        
}catch(Exception e){
    e.printStackTrace();
}

 

for문에서 remove 시
java.util.ConcurrentModificationException 발생

 

해당 값을 for문 내에서 remove 하게 되면, swap이 자동으로 발생해 List의 size가 달라지게 됨.

이러한 문제 때문에 Java에서는 remove시 Iterator 사용을 권장 하고 있습니다.

(remove 없이 단순 요소 접근은 for문을 사용하는 것이 속도면에서 우수 합니다. )

 

try{
    List<Integer> testArrayList = new ArrayList<Integer>();
    testArrayList.add(1);
    testArrayList.add(2);
    testArrayList.add(3);
    testArrayList.add(4);
    testArrayList.add(5);
          
    System.out.println(testArrayList);
    for (Iterator<Integer> iter = testArrayList.iterator(); iter.hasNext(); ) {
        int value = iter.next();
        if (value==3) {
            iter.remove();
        }
    }
    System.out.println(testArrayList);
        
}catch(Exception e){
    e.printStackTrace();
}

 

그리고 iterator 반복문 내에서 next() 메소드를 여러번 실행하면, 그만큼 증가한 시점의 Object 값을 가져오게 됩니다.

위의 예에서 int value = iter.next(); 를 한 이유가 그것입니다. 사용하지 않는다면

 

if(iter.next()==3){
    iter.next().remove();
}

 

이렇게 코딩을 하실텐데, 이러면 iter.next() 를 2번 실행하게 되어 원하지 않는 값에 접근 하게 됩니다.

if조건문의 next() = 3, if문 내의 next() = 4가 되게 되죠.

주의 하시기 바랍니다!

 

※ Iterator 메소드

Method Name Explanation
hasNext 해당 Iteration의 다음 요소가 있으면 true, 없으면 false
next 해당 Iteration의 다음요소를 리턴
remove 해당 요소를 제거

 

※ ListIterator 메소드

Method Name Explanation
add 해당 List에 요소 추가
hasNext 정방향 순회 시 요소가 있으면 true 없으면 false
hasPrevious 역방향 순회 시 요소가 있으면 true 없으면 false
next List의 다음 요소를 반환. 커서를 정방향으로 이동
nextIndex List의 다음 요소의 Index를 리턴
previeous List 이전 요소를 반환, 커서를 역방향으로 이동
previeousIndex List의 이전 요소의 Index를 리턴
remove 해당 요소를 제거
set 해당 요소로 수정

 

Link : JAVA Collection Framework 정리, 자바 컬렉션, List, Set, Map, Queue, Stream 2부 Set

반응형

댓글

💲 추천 글