ch11 - 7 ArrayList
List 인터페이스는 순서를 유지 하고, 중복을 허용 한다.
List 인터페이스를 구현 받은 클래스들이 존재 한다.
Vector은 오래된 클래스라서 저것과 유사한 클래스가 ArrayList 이다.
굳이 차이점을 뽑자면,
Vector 클래스는 자체적으로 동기화를 지원하고, ArrayList는 자체적으로 동기화를 지원 하지 않는다.
List 인터페이스를 구현 받은 클래스들은 모두, 데이터의 저장 공간으로 배열을 사용 한다.
ch11 - 8 ArrayList의 메서드
위의 메서드는 ArrayList의 생성자 이다.
첫번째는 기본생성자 이고,
두번째는 매개변수로 어떤 컬렉션을 주면, 그 컬렉션 안에 저장 되어 있는 데이터를 ArrayList에 저장 할 수 있다.
세번째는 배열의 길이를 매개변수로 넣어서 ArrayList를 생성 할 때 길이를 지정 할 수 있다.
위의 메서드는 ArrayList 에 데이터를 추가 하기 위한 메서드 이다.
첫번째는
add() 메서드를 사용해서 ArrayList에 데이터를 저장하는데, 반환 타입이 true or false 이다.
대부분은 true를 반환 한다고 보면 된다.
두번째는
인덱스 == 저장 위치를 지정하고, 데이터를 저장 한다.
그냥 추가하면 제일 뒤의 인덱스에 저장 된다.
세번째는
특정한 컬렉션을 넣으면 그 컬렉션이 가지고 있는 데이터 (요소) 를 모두 추가 한다.
네번째는
특정한 컬렉션을 넣을때, 그 컬렉션이 가지고 있는 요소를 특정 인덱스 부터 저장 할 수 있다.
위의 메서드는 데이터를 삭제 하는 메서드 이다.
위의 메서드는 데이터를 검색 (찾는) 메서드 이다.
int indexOf(Object o) 메서드는 데이터를 찾지 못했을 경우, 반환값으로 -1 을 던진다.
contains() 메서드는 객체가 포함되는지를 묻는 메서드 이고,
Object get(int index) 메서드는 특정 위치에 있는 객체를 반환 한다.
Object set() 메서드는 특정 위치에 있는 객체를 다른 객체로 교체 한다.
위의 메서드는 여러 가지 기능을 하는 메서드 인데,
첫번째는,
반환값이 List 인것을 볼 수 있다.
지정한 인덱스 부터 지정한 인덱스 까지를 잘라서 그것을 새로운 List에 저장하고 그 List를 반환 한다.
두번째는,
ArrayList의 객체 배열을 반환 한다.
모든타입을 의미하는 == Object 타입에 [ ] 을 붙힌 모습을 볼 수 있다.
== 객체 배열
그 외에 비어있는지 확인하는 메서드와,
ArrayList의 빈 공간을 제거하는 메서드도 있고,
ArrayList의 저장된 객체의 개수를 확인 할 수도 있다.
[ 예제 ]
ArrayList list1 = new ArrayList(10);
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 list2 = new ArrayList(list1.subList(1,4));
print(list1, list2);
길이가 10인 배열리스트를 생성하고, add() 메서드를 사용 해서 래퍼클래스인 Integer을 저장하는것을 확인 할 수 있다.
배열리스트는 각 공간에 객체를 저장하며,
list1.add(5);
오토박싱 기능에 의해 컴파일러가 기본형을 참조형으로 자동 변환 해줌으로써, 간단하게 5라고 작성해도 된다.
subList(1, 4) 메서드는 1 <= x < 4 이다.
자바에 모든 subXxx() 메서드는 자를때 뒤에 숫자는 포함 하지 않는다.
list1:[5, 4, 2, 0, 1, 3]
list2:[4, 2, 0]
위와 같은 결과를 확인 할 수 있다.
ArrayList list2 = new ArrayList(list1.subList(1,4));
참고로 이 코드는, ArrayList(Collection c) 생성자를 사용한 모습인데,
1번째 인덱스 부터 3번째 인덱스 까지의 객체 데이터를 그대로 ArrayList 타입의 list2 참조변수에 복사하는 느낌 이다.
저것을 풀어서 쓰면, 아래와 같다.
List sub = list1.subList(1, 4);
List list2 = new ArrayList(sub);
배열리스트 내부의 객체 데이터를 오름차순으로 정렬하는 방법.
Collections.sort(list1); // list1과 list2를 정렬한다.
Collections.sort(list2); // Collections.sort(List l)
print(list1, list2);
Collections 라는 유틸 클래스가 존재 한다.
이 클래스 내부에 sort() 라는 오름차순으로 정렬해주는 메서드를 가지고 있고,
Collection 인터페이스와 헷갈리지 말자.
list1:[0, 1, 2, 3, 4, 5]
list2:[0, 2, 4]
ch11 - 10 ArrayList 에 저장된 객체의 삭제 과정
- ArrayList 에 저장된 세 번째 데이터 ( data[2] ) 를 삭제 하는 과정.
>> list.remove(2); 를 호출.
1) 삭제할 데이터 아래의 데이터를 한 칸씩 위로 복사해서 삭제할 데이터를 덮어쓴다.
2) 데이터가 모두 한 칸씩 이동 했으므로 마지막 데이터는 null 로 변경 한다.
3) 데이터가 삭제되어 데이터의 개수가 줄었으므로 size의 값을 감소 시킨다.
만약 마지막 데이터를 삭제하는 경우, 1의 과정 (배열 복사) 은 필요 없게 된다.
그냥 마지막 데이터를 null 로 바꿔주고 배열의 size를 - 1 하면 된다.
그래서 마지막 데이터를 지우는건 부담이 크게 되지 않는데,
처음 또는 중간 어딘가에 데이터를 지워야 하는 경우는 삭제할 데이터 아래의 데이터를 한칸씩 다
땡겨와서 위로 복사 하고 덮어씌워야 하기 때문에 부담이 많이 가게 된다.
- ArrayList 에 저장된 첫 번째 객체 부터 삭제 하는 경우 (배열 복사가 당연히 발생 된다)
// 아래와 같은 코드가 있다고 가정.
for(int i = 0; i < list.size(); i++) {
list.remove(i);
}
데이터를 모두 삭제 하려고 for문을 루프 시켰지만, 아래 이미지와 같이 모두 지워지지 않는 결과를 볼 수 있다.
list.size()는 5인데, 5번을 루프 시키지만, 한바퀴 돌때마다 size()는 당연히 작아지고,
remove(i) 의 i는 0, 1, 2, .. 하면서 ++ 이 되지만,
배열리스트 내부의 객체가 삭제 될때마다 한칸씩 올려지면서 결국 데이터가 남게 된다.
그래서 어떻게 해야 하냐면,
ArrayList 에 저장된 마지막 객체 부터 삭제 한다. 이러면 배열 복사가 발생 하지 않는다.
즉, 데이터의 이동이 없게 된다.
위에서 부터 지우면 빈칸을 채우려고 앞으로 계속 복사가 되는데,
아래서 부터 지우면 그런일이 없어 진다.
for(int i = list.size() - 1; i >= 0; i--) {
list.remove(i);
}
깔끔 하게 지워지는 것을 확인 할 수 있다.
배열의 복사가 이뤄지지 않기 때문에, 빠르고, 모두 지워진다.
결론은, 성능상의 이점을 위해서라도 지울 때 반복문을 거꾸로 돌려버리면 좋다.
ch11 - 11 Java API 보는 방법
/jdk 설치 경로 /src.zip 안에서 볼 수 있고,
IDE 안에서 보고 싶으면, 아래와 같이 하면 된다.
찾고자 하는 선언된 ArrayList 를 우클릭 하고,
Open Declaration 을 클릭 한다.
그러면 이렇게 확인 할 수 있다.
'Java의 정석 > 컬렉션 프레임워크' 카테고리의 다른 글
Stack / Queue (스택 / 큐) (0) | 2023.09.17 |
---|---|
LinkedList 와 ArrayList 의 비교 (0) | 2023.09.17 |
Collection, List, Set, Map (0) | 2023.09.17 |
컬렉션 프레임워크와 핵심 인터페이스 (0) | 2023.09.17 |
Map (링크드 해시맵) 예제 02 (0) | 2023.08.26 |