java.lang.Object
-> java.util.AbstractCollection<E>
-> java.util.AbstractList<E>
-> java.util.ArrayList<E>
ArrayList의 가장 상위 부모는 Object 클래스다.(모든 Class의 상위 부모는 Object)
그 다음은 AbstractCollection, AbstractList의 순으로 확장 했다.
Object를 제외한 나머지 부모 클래스들은 이름 앞에 Abstract이 붙어 있다. 즉 이 클래스들은 abstract 클래스다.
abstract 클래스는 일반 클래스와 비슷하지만, 몇몇 메소드는 자식에서 구현하라고 abstract로 선언한 메소드들이 있는 클래스를 말한다.
공통적인 메서드를 구현할 때 사용한다.
AbstractCollection은 Collection 인터페이스 중 일부 공통적인 메소드를 구현해 놓은 것이며, AbstractList는 List 인터페이스 중 일부 공통적인 메소드를 구현해 놓은 것이라고 볼 수 있다.
Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess
이와 같은 인터페이스들을 ArrayList가 구현했다는 것은 각 인터페이스에서 선언한 기능을 ArrayList에서 사용할 수 있다는 말이다.
ArrayList는 3개의 생성자를 가진다.
size() 메소드는 ArrayList의 저장 공간 개수를 말하는 게 아니라 들어가 있는 개수를 의미한다.
참고로 Array의 length는 배열에 넣을 수 있는 공간의 개수.
add(int index, E e)를 이용해 특정 인덱스에 값을 넣으려고 하면 IndexOutOfBoundsException이라는 예외가 발생할 수 있다.
예를들어 ArrayList()생성자를 이용해 만들었다면 저장할 수 있는 공간은 10개인데 11번째에 데이터를 넣으려 하면 일어난다.
ArrayList는 내부적으로 Array를 이용해 구성되어 있기 때문에 Array에서 나는 에러가 그대로 나는 것이다.
add()를 이용해 할당된 공간보다 많이 저장하려고 하면 크기를 늘리는 작업이 동반되어 어플리케이션에 영향을 줄 수 있다. 따라서 예측 가능하다면 예측 가능한 초기 크기를 지정할 것이 권장된다.
기존의 ArrayList를 깊은복사를 이용해 새로운 ArrayList를 사용하고 싶다면 addAll을 사용해도 되지만
new ArrayList(list); 이런식으로 사용하는게 더 깔끔하고 좋다.
만약 김철수라는 값이 두개가 있는데
뒤에있는 김철수를 찾고 싶다면 lastIndexOf
앞에있는 김철수를 찾고싶다면 indexOf를 사용하면 된다.
배열로 만들고 싶다면 toArray()보다 toArray(T[] a)를 사용하는게 좋다.
그 이유는 toArray()는 Object 타입의 배열로만 리턴을 하기 때문에 타입 추정이 어렵다.
그리고 toArray(T[] a)를 사용할 때 ArrayList보다 배열 초기화 크기가 더 크다면 메모리의 낭비가 일어나고 더 적다면 데이터가 들어가지 않으니 크기가 0인 배열을 넘겨주는 것이 가장 좋다.
remove(Object o)는 동일값이 있다면 앞에 하나만 제거한다.
만약 해당 동일값을 다 지우고 싶다면 removeAll(Collection<? extends E> c)을 이용하면 깔끔하다.
ArrayList는 Thread Safe하지 못하다 따라서 여러 쓰레드에서 안전하게 만들고 싶다면
List list = Collection.synchronizedList(new ArrayList(...));
이렇게 생성해야한다 그렇지 않으면 원하는 값이 나오지 않을 수 있다.
자바로 개발하면서 ArrayList를 많이 쓰고 꽤 잘 활용하고 있다고 생각했는데 공부를 해보고 나니 기억 저 편에 있어 활용하지 못한 것들이 많았던 것 같다.