ArrayList
ArrayList
저번시간에 LIst인터페이스에 대해서 알아보았다.
List인터페이스의 특징은, 순서가 있고 중복을 허용한다는 것이다.
Lsit인터페이스로 구현한 대표적인 Collection클래스는 ArrayLIst와 LinkedList 가 핵심이다.
그중에 하나인 ArrayList에 대해 알아보자.
- ArrayList는 기존의 Vector를 개선한 것으로 구현원리와 기능적으로 동일
ArrayList와 달리 Vector는 자체적으로 동기화처리가 되어 있다. - List인터페이스를 구현하므로, 저장순서가 유지되고 중복을 허용한다.
- 데이터의 저장공간으로 배열을 사용한다.(배열기반)
ArrayList와 Vector는 거의 같지만, Vector를 개선시킨 것이 ArrayList이다.
가능하면 ArrayList를 사용하는게 좋다.
Vector와 ArrayList는 어떤 차이가 있냐면, 동기화부분에 차이가 있다.
Vector는 동기화가 되어있고, ArrayList는 동기화가 되어있지 않다.
동기화에 대한 자세한 내용은 13장 쓰레드에서 알아볼 것이다.
ArrayList는 List인터페이스를 구현하므로, 저장순서가 유지되고 중복을 허용한다.
ArrayList는 데이터(객체)의 저장공간으로 배열을 사용한다.
그래서 Vector클래스의 소스를 보면,
그 안에 Object[] 객체 배열이 있는데, 다형성에서 배웠듯, 조상타입의 참조변수로 자손객체를 다룰 수 있는 것처럼,
Object[]에는 모든 종류의 객체를 저장할 수 있다.
정리하면, ArrayList는 List인터페이스를 구현해서, 저장순서가 유지되고, 중복이 허용되며, 데이터의 저장공간으로 배열을 사용한다.
ArrayList의 메서드
ArrayList가 어떤 메서드들을 가지고 있는지 살펴보자.
우선, 생성자다.
첫번째는 기본생성자다.
두번째 생성자는, 매개변수로 어떤 Collcetion을 주면, 그 Collection에 저장되어 있는 것을 저장하는 ArrayList가 생성된다. Collection들끼리 변환할 때 많이 사용한다.
세번째 생성자는, 매개변수에 배열의 길이를 지정해준다.
앞서 배웠지만, 배열은 한번 만들면 그 길이를 변경할 수 없다.
따라서, ArrayList를 만들때 자신이 저장하려고 하는 객체의 갯수만큼 ArrayList배열의 길이를 지정해줘야 한다.
경우에 따라 배열에 객체를 추가하거나 삭제를 해줄 수도 있으니 넉넉하게 지정해주는 것이 좋다.
그렇지 않으면, 공간이 부족할 때마다 배열을 다시 새로만들고, 복사해야하는 과정을 거쳐야하기 때문에 성능이 떨어진다.
그래서 ArrayList를 만들 때는, ArrayList가 사용할 배열의 길이를 적절히 지정해주는 것이 중요하다.
이번에는 추가하는 메서드이다.
ArrayList에 어떤 객체를 저장하려면, add(Object o)라는 메서드를 사용하면 된다. 매개변수로는 저장할 객체를 준다.
그러면 해당 객체가 ArrayList에 추가된다. 성공하면 true를 반환하고, 실패하면 false를 반환한다.
그리고 그냥 add(Oject o)를 사용하면 맨 뒤에 추가가 되는데,
add(int index, Object element) 메서드로 저장위치를 지정해서 어느 위치에 저장할지 지정해줄 수 있다.
addAll(Coelction c)라는 메서드로는 Collection이 가지고 있는 요소를 그대로 저장할 수 있다.
그리고 이때도, addAll(int index, Collection c)메서드로 추가할 위치를 정해줄 수 있다.
이번에는 삭제하는 메서드이다.
저장한 것을 삭제할 떄는 remove(Object o)를 사용한다
그리고 특정 위치에 있는 객체를 삭제할 때는, remove(int index)를 사용한다.
그리고 removeAll(Collection c)는 Collection에 있는 객체들을 삭제하는 메서드이다.
celar()는 ArrayList에 저장되어 있는 모든 객체를 삭제하는 메서드이다.
이번에는 검색하는 메서드이다.
indexOf(Object o)는 해당 객체가 몇번째 인덱스에 저장되어 있는지 찾는 것이다. 왼쪽에서 오른쪽으로 찾는다.
못찾으면 -1을 반환한다.
그리고 lastIndexOf(Object o)는 오른쪽끝에서부터 왼쪽으로 객체를 찾는다.
contains(Object o)는 지정한 객체가 존재하는지 검색하는 것이다.존재하면 true, 없으면 false를 반환한다.
get(int index)는 특정 위치에 있는 객체를 반환한다. 객체를 읽는 것이다.
set(int index, Object element)는 특정위치에 있는 객체를 다른 객체로 바꾸는 것이다. get과 set 한쌍으로 되어있다.
그리고 subList(int formIndex, int toIndex)는 from~to 사이에 있는 객체들을 뽑아서 새로운 리스트를 만든다.
toArray()는 ArrayList가 가지고있는 객채의 배열을 반환한다.
toArray(Object[] a)
isEmpty()는 ArrayList가 비어있는지 확인하는 메서드이다.
trimToSize()는 빈공간을 제거하는 것이다.
size()는 ArrayList에 저장된 객체의 갯수를 반환한다.
ArrayList에 저장된 객체의 삭제 과정
ArrayList에 있는 객체를 삭제할 때, 어떤일이 일어나는지 자세히살펴보자.
인덱스 2에 있는 것을 삭제하려고 한다. list.remove(2)를 하면 index가 2인 객체를 삭제한다.
그러면, 인덱스 2 뒤의 요소들을 한칸씩 위로 복사해서 삭제할 데이터를 덮어쓴다.
그러면 2가 자동으로 없어진다. 대신에 마지막에 복사하고 남은 마지막 요소는 남아있게 되는데,
이것을 null로 바꿔준다.
그다음에, size(저장된 객체의 갯수)가 5였는데, 이것을 4로 바꿔준다.
삽입할 때는 반대로, 지정한 인덱스 2의 뒤의 데이터를 한칸 뒤로 복사해서 값을 집어넣고, size를 증가시킨다.
삭제하는 과정 반대로 하면 된다.
※ 만약에, 마지막 데이터를 삭제하는 경우, 데이터를 옮길 필요가 없다. 즉 1의 과정이 필요없다.
그냥 마지막요소에 null을 집어넣고 size를 감소시키면 된다.
1번작업, 즉 복사하는 작업이 부담이 많이 가는 작업이라서 되도록이면 1번과정이 일어나지 않도록 하는 것이 좋다.
위의 예제를 보자.
만약, ArrayList에 저장된 객체를 전부 삭제하기위해
위와같은 반복문을 만들었다고 가정해보자.
size가 5이고, i가 0부터 1씩 증가하면서 삭제한다.
그러면 remove(0)로 0첫번째 인덱스부터 지워지고 나머지 인덱스에있던 것들이 전부 복사되어 한칸 위로 올라가서 저장된 상태가 되고,
이번에는 remove(1)로 두번째 인덱스 에 있는게 지워지고,
그다음에 remove(2)로 세번째 인덱스에 있는 것이 지워지는 것을 반복해서
맨 오른쪽 그림과 같은 상태가 될 것이다.
앞에부터 하나씩 다 지우려고 했지만, for문을 다 돌고나서도 앞에 데이터가 남아있다는 것이다.
그이유는, 삭제할 때마다 아래에 있던 데이터들이 위로 복사되어 채워지기 때문이다.
그러면 어떻게 삭제해야될까?
맨 뒤에부터 삭제하면 된다.
list.size()-1 즉, index4부터 시작해서 끝을 지우고,
또 마지막을 지우고, 이것을 반복하면,
배열복사, 데이터 이동 없이 지워진다.
즉, 빠르게 잘 지울 수 있다.
잘 기억해두자. 반드시 겪을 문제일 수 있다.
점점 실력이 증가함에 따라,
실제 Java에서는 해당 클래스를 어떻게 구현했는지 궁굼할 수도 있을 것이다.
그럴때, 해당 소스를 직접 보면 좋다.
맥 기준으로
jdk설치경로의 src.zip 파일을 압축해제하면 볼 수 있다.
Library/Java/JavaVirtualMachines/openjdk-17.0.2/Contents/Home/lib/src.zip
혹은 인텔리제이에서,
보고싶은 클래스를 우클릭한 후,
Go To → Declaration or Usages 를 클릭하게 되면, (혹은 해당 클래스에 커서를 놓고 command + B를 누르게 되면)
이렇게 ArrayList 클래스의 실제 소스를 볼 수 있다.
'JAVA' 카테고리의 다른 글
Stack과 Queue (0) | 2022.04.28 |
---|---|
LinkedList (0) | 2022.04.28 |
Collection, List, Set, Map (0) | 2022.04.27 |
컬렉션 프레임웍과 핵심 인터페이스 (0) | 2022.04.27 |
형식화 클래스 SimpleDateFormat (0) | 2022.04.27 |
댓글
이 글 공유하기
다른 글
-
Stack과 Queue
Stack과 Queue
2022.04.28 -
LinkedList
LinkedList
2022.04.28 -
Collection, List, Set, Map
Collection, List, Set, Map
2022.04.27 -
컬렉션 프레임웍과 핵심 인터페이스
컬렉션 프레임웍과 핵심 인터페이스
2022.04.27