본문 바로가기

Java

[Java] 컬렉션 프레임워크, ArrayList

목차

  • 컬렉션 프레임워크란 무엇일까?
  • 컬렉션 프레임워크의 핵심 인터페이스, 특징
  • 컬렉션 인터페이스의 메서드
  • ArrayList의 메서드
  • ArrayList 예제
  • ArrayList에 저장된 객체의 삭제과정(배열 복사 문제)

 

컬렉션(collection)

 

여러 객체(데이터)를 모아 놓은 것을 의미

 

 

프레임워크(framework)

표준화, 정형화된 체계적인 프로그래밍 방식

라이브러리 + 표준화된 프로그래밍 방식

제한적이지만 생산성이 높아지고 유지보수가 쉬워짐

표준화 되지 않으면 다른 사람이 짜놓은 코드를 다른 사람이 보기 어렵다.

 

 

컬렉션 프레임워크

컬렉션(다수의 객체)을 다루기 위한 표준화된 프로그래밍 방식

컬렉션을 쉽고 편리하게 다룰 수 있는 다양한 클래스를 제공(저장, 삭제, 검색, 정렬)

많은 수의 데이터(다수의 객체)를 다루는데 유용한 클래스를 제공하고 있다.

다수의 데이터를 다루는 클래스들이 있었지만 표준화가 안 되어있었다.

java.util 패키지에 포함(JDK 1.2)

 

 

컬렉션 클래스

다수의 데이터를 저장할 수 있는 클래스(예: Vector, ArrayList, HashSet)

 

 

 

 

컬렉션 프레임워크의 핵심 인터페이스

 

 

출처: 남궁성 자바강의, 링크:https://www.youtube.com/watch?v=z9GpUGoYCw4&list=PLW2UjW795-f6xWA2_MUhEVgPauhGl3xIp&index=119

 

 

 

List: (저장) 순서가 있고, 중복을 허용!!

대기자 목록: 명단에 있는 순서로 대기자를 불러야 함, 명단에 이름이 같은 경우도 있음.

 

Set: 순서가 없고, 중복을 허용하지 않음(List와 정반대의 성격을 가지고 있음, 집합의 특징)

네발 동물의 집합: 개, 고양이, 사자, 호랑이, 꼬끼리(순서 중요 x)

 

Map: 두 값을 연결한 것, 순서는 중요하지 않음, 키는 중복 허용하지 않음, 값은 중복허용!

우편번호, 전화번호, 주민등록번호, 아이디는 중복X, 비밀번호는 중복O

 

표준화의 결과로 구현 클래스(ArarryList) 이름 뒤에 인터페이스 이름인 List, Set, Map 같은 단어들이 붙었음.

아닌 것들은 표준화되기 전에 만들어진 클래스들!

 

List, Set의 공통 부분을 뽑아서 Collection이라는 인터페이스를 정의를 하였다.

Map은 키와 값을 한쌍으로 묶는것 이기 때문에 단일 값만 저장하는 List, Set 과는

특성이 많이 달라서 공통 부분을 뽑아내지 못했다!

 

우리가 다루는 데이터의 특징에 맞는 클래스를 선택하면 된다!!!

 

 

 

 

Collection 인터페이스의 메서드

 

 

 

 

 

 

List 인터페이스의 - 순서 O, 중복 O

 

 

 

 

 

Set 인터페이스의 - 순서 X, 중복 X

 

 

 

 

Map 인터페이스의 - 순서 X, 중복(키 X, 값 O) 

 

 

 

 

 

 

 

 

ArrayList

ArrayList는 기존의 Vetor를 개선한 것으로 구현원리와 기능적으로 동일

ArrayList와 달리 Vetor는 자체적으로 동기화처리가 되어 있다.

List 인터페이스를 구현하므로, 저장순서가 유지되고 중복을 허용한다.

데이터의 저장공간으로 배열을 사용한다.(배열기반)

Vector 클래스 안에는 Object 배열(모든 종류의 객체를 담기 위한 배열)이 있다.

 

 

 

ArrayList의 메서드

생성자

  • ArrayList( ): 기본생성자
  • ArrayList(Collection c): 매개변수로 컬렉션을 주면 컬렉션의 저장되어 있는 데이터를 ArrayList를 만든다.(켈력션 간의 변환)
  • ArrayList(int initialCapacity): 배열의 길이를 넣어준다.(내가 저장할려고 하는 객체의 갯수만큼)

 

추가 메서드

  • boolean add(Object o): 저장할 객체를 준다. 성공한다면 true 반환, 실패 시 false 반환
  • void add(int index, Object element): 저장위치(index) 지정, 객체를 저장
  • boolean addAll(Collection c): 컬렉션을 주면 안에 있는 요소들을 저장
  • boolean addAll(int index, Collection c): 저장 위치 지정

 

삭제 메서드

  • boolean remove(Object o): 삭제할 객체를 준다.
  • Object remove(int index): 특정 위치에 있는 객체 삭제 
  • boolean removeAll(Collection c): 컬렉션을 지정해주면 안에 있는 요소(객체)들을 삭제
  • void claer( ): ArrayList에 있는 모든 객체를 삭제

 

검색 메서드

  • int indexOf(Object o): 찾으려는 객체가 몇 번째 있는지 반환해줌. 못 찾으면 -1 반환, 왼=>오
  • int lastIndexOf(Object o): 오 =>왼 방향으로 객체를 찾는다. 위와 똑같음.
  • boolean contains(Object o): 지정된 객체가 있는지(존재하는지 ?) 있으면 true, 없다면 false 반환
  • Object get(int index): 위치해 있는 객체 반환(읽기)
  • Object set(int index, Object element): 특정 위치에 있는 객체를 다른 것으로 변경
  • List subList(int fromIndex, int toIndex): 시작위치(from) ~ 위치(to) 사이에 있는 객체들을 뽑아서 새로운 List로 만듬.
  • Object[ ] toArray( ): ArrayList가 가지고 있는 객체 배열을 반환
  • Object[ ] toArray(Object [ ] a): 
  • boolean isEmpty( ): ArrayList가 비어있는지  
  • void trimToSize( ): 빈 공간을 제거
  • int size( ): ArrayList에 저장된 객체의 개수를 반환 
public class ArrayListEx1 {
    public static void main(String[] args) {
        // 기본 길이(용량, capacity)가 10인 ArrayList를 생성
        ArrayList list1 = new ArrayList(10);
        // list1.add(Integer.valueOf(5));
        // ArrayList에는 객체만 저장가능
        // list1.add(5); 오토박싱 (기본형 => 참조형)
        list1.add(new Integer(5));
        list1.add(new Integer(4));
        list1.add(new Integer(2));
        list1.add(new Integer(0));
        list1.add(new Integer(1));
        list1.add(new Integer(3));

        // ArrayList(Collection c)
        // subList로 만들어진 List는 읽기 전용
        ArrayList list2 = new ArrayList(list1.subList(1, 4)); // 1 <= x < 4, [4, 2, 0]
        print(list1, list2);

        // Collection은 인터페이스, Collections는 클래스(Collection을 다루기 필요한 메서드들을 제공)
        Collections.sort(list1); // list과 list2를 정렬한다.(기본적으로 오름차순)
        Collections.sort(list2); // Collections.sort(List l)
        print(list1,list2);
        
        // list1이 list2의 모든 요소를 포함하고 있느냐?
        System.out.println("list1.containsAll(list2) = " + list1.containsAll(list2));
        System.out.println();

        list2.add("B");
        list2.add("C");
        // 추가할 위치를 지정해줬음 index = 3번째에 기존에 있는 것들은 한칸 씩 밀림
        list2.add(3, "A");
        print(list1, list2);
        
        // 인덱스 3에 있는 것을 AA로 변경(치환)
        list2.set(3, "AA");
        print(list1, list2);

        // 얘는 문자열!! 나머지는 Integer 타입
        list1.add(0, "1");
        // 문자열 1이 어디 인덱스에 있는지!! 알려줌, 0번 째
        System.out.println("index = " + list1.indexOf("1")); // String
        System.out.println("index = " + list1.indexOf(new Integer(1))); // int
        System.out.println();

        // 지정위치(index)에 있는 객체를 지운다.
        list1.remove(0);
        list1.remove(1); // 첫 번째 index를 지운다. boolean remove(), Object remove()?
        list1.remove(new Integer(1)); // 이렇게 지워주자!
        print(list1, list2);

        // list1에서 list2와 겹치는 부분만 남기고 나머지는 삭제한다. [4,5] 삭제
        System.out.println("list1.retainAll(list2) = " + list1.retainAll(list2));
        print(list1, list2);

        // list2에서 list1에 포함된 객체들을 삭제한다.
        // list2.size = 6, list2는 인덱스 5까지
        // list2의 인덱스 5 ~ 0 까지 차례로 포함되어 있는지 확인하고 같다면 삭제
        int n = 0;
        for (int i = list2.size() - 1; i >= 0; i--) {
            if (list1.contains(list2.get(i))) {
                list2.remove(i);
            }
            System.out.println("======================");
            System.out.println((++n) + "번 째 시도 중");
            print(list1, list2);
        }
    }
    static void print(ArrayList a, ArrayList b) {
        System.out.println("list1: " + a);
        System.out.println("list2: " + b);
        System.out.println();
    }
}
list1: [5, 4, 2, 0, 1, 3]
list2: [4, 2, 0]

list1: [0, 1, 2, 3, 4, 5]
list2: [0, 2, 4]

list1.containsAll(list2) = true

list1: [0, 1, 2, 3, 4, 5]
list2: [0, 2, 4, A, B, C]

list1: [0, 1, 2, 3, 4, 5]
list2: [0, 2, 4, AA, B, C]

index = 0
index = 2

list1: [0, 2, 3, 4, 5]
list2: [0, 2, 4, AA, B, C]

list1.retainAll(list2) = true
list1: [0, 2, 4]
list2: [0, 2, 4, AA, B, C]

======================
1번 째 시도 중
list1: [0, 2, 4]
list2: [0, 2, 4, AA, B, C]

======================
2번 째 시도 중
list1: [0, 2, 4]
list2: [0, 2, 4, AA, B, C]

======================
3번 째 시도 중
list1: [0, 2, 4]
list2: [0, 2, 4, AA, B, C]

======================
4번 째 시도 중
list1: [0, 2, 4]
list2: [0, 2, AA, B, C]

======================
5번 째 시도 중
list1: [0, 2, 4]
list2: [0, AA, B, C]

======================
6번 째 시도 중
list1: [0, 2, 4]
list2: [AA, B, C]

 

 

 

ArrayList에 저장된 객체의 삭제과정

 

ArrayList에 저장된 세 번째 데이터(data[2])를 삭제하는 과정.

list.remove(2); //호출(인덱스가 2인 데이터 삭제)

 

1. 삭제할 데이터 아래의 데이터를 한 칸씩 위로 복사해서 삭제할 데이터를 덮어쓴다.

System.arraycopy(data, 3, data, 2, 2);
data[3]에서 date[2]로 2개의 데이터를 복사하라는 의미이다.(3, 4를 복사해서 한 칸 앞으로)

 

 

2. 데이터가 모두 한 칸씩 이동했으므로 마지막 데이터는 null로 변경한다.

data[size - 1] = null; // 실제 저장된 객체가 들어있는 개수 - 1(배열의 끝부분)

 

 

3. 데이터가 삭제되어 데이터의 개수가 줄었으므로 size의 값을 감소시킨다.

 

size--;

 

 

참고

  • list.add(2) 메서드의 경우도 data[3]로 2개의 데이터를 아래로 복사해서 동일한 과정을 거친다.
  • 마지막 데이터를 삭제하는 경우, 1번 과정(배열의 복사)은 필요없다.
  • 이동과정(복사과정)이 있는 부담이 많이 가는 작업이므로 되도록 1번 과정이 일어나지 않도록 하자!

 

그럼 어떻게 1번 과정이 일어나지 않게 만들까?

1. ArrayList에 저장된 첫 번째 객체부터 삭제하는 경우(배열 복사 발생) => 다 삭제되지 않음!!!!

for(int i = 0; i < list.size(); i++) {
    list.remove(i); // 1부터 5까지 반복하면서 배열 복사 발생
}

 

 

2. ArrayList에 저장된 마지막 객체부터 삭제하는 경우(배열 복사 발생안함) => 빠르고 깔끔하게 지워짐!!

for(int i = list.size() - 1; i >= 0; i--) {
    list.remove(i); // 뒤에서 부터 삭제하면 배열 복사안함
}

 

'Java' 카테고리의 다른 글

[Java] Stack과 Queue  (0) 2024.05.07
[Java] LinkedList 특징  (0) 2024.05.06
[Java] Arrays로 배열 다루기  (0) 2024.05.02
[Java 복습] 추상 클래스, 인터페이스  (0) 2024.05.01
[Java] 예외 처리 활용  (0) 2024.04.23