Collection 인터페이스
자바에서 Set, List, Queue 는 Collection
이라는 인터페이스를 구현하고 있습니다.
Collection 인터페이스는 다음과 같이 선언되어 있습니다.
public interface Collection<E> extends Iterable<E>
Iterable<E>
이라는 인터페이스를 extends 하였는데 이 인터페이스에 대해 잠깐 알아보겠습니다.
Iterable
이 인터페이스에 선언되어 있는 메소드는 단지 하나입니다.
Iterator<T> iterator();
이며, 이 메소드는 Iterator<T>
인터페이스를 리턴합니다.
Iterator<T>
인터페이스에는 추가 데이터가 있는 지 확인하는 hasNext()
, 현재 위치를 다음 요소로 넘기고 그 값을 리턴해주는 next()
, 데이터를 삭제하는
remove()
가 있습니다.
결론적으로, Collection 인터페이스가 Iterable 인터페이스를 확장했다는 의미는 Iterator 인터페이스를 사용하여 데이터를 순차적으로 가져올 수 있다는 의미입니다.
Collection 에 선언된 주요 메소드
boolean add(E e)
: 요소 추가boolean addAll(Collection)
: 매개변수로 넘어온 컬렉션 모든 요소 추가void clear()
: 컬렉션에 있는 모든 요소 데이터 지우기boolean contains(Object)
: 매개변수로 넘어온 객체와 동일한 객체가 해당 컬렉션에 있으면 true 반환boolean containsAll(Collection)
: 매개변수로 넘어온 컬렉션에 있는 객체들이 해당 컬렉션에 모두 동일한 값들이 있다면 true 반환boolean equals(Object)
int hashCode()
boolean isEmpty()
Iterator iterator()
boolean remove(Object)
boolean removeAll(Collection)
boolean retainAll(Collection)
: 매개변수로 넘어온 객체들만을 컬렉션에 남겨 둔다int size()
: 요소의 개수를 리턴Object[] toArray()
: 컬렉션에 있는 데이터들을 배열로 복사<T> T[] toArray(T[])
: 컬렉션에 있는 데이터들을 지정한 타입의 배열로 복사
List 인터페이스
Collection
인터페이스를 확장한 List
인터페이스는 다른 Set, Queue
와 다른 점은 배열처럼 순서가 있습니다.
List 인터페이스를 구현한 클래스는 ArrayList
, Vector
, Stack
, LinkedList
이고, 이중 ArrayList와 Vector
는 확장 가능한 배열이며 차이점은 ArrayList
는
Thread Safe 하지 않지만 Vector
는 Thread Safe 합니다.
ArrayList
상속관계
java.lang.Object
ㄴ java.util.AbstractCollection<E>
ㄴ java.util.AbstractList<E>
ㄴ java.util.ArrayList<E>
AbstractCollection
은 Collection
인터페이스 중 일부 메소드를 구현해 놓은 것이며, AbstractList
는 List
인터페이스 중 일부 메소드를 구현해놓았습니다.
ArrayList가 구현한 인터페이스
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
추가로 Collection<E>
과 Iterable<E>
이므로 이 인터페이스들이 선언한 메소드들을 사용할 수 있습니다.
ArrayList 생성자
ArrayList()
: 객체를 저장할 공간이 10개인 컬렉션을 만듭니다. 단, 10개 만들었다고 랜덤으로 아무데나 넣으면IndexOutOfBoundsException
이 발생됩니다.ArrayList(Collection<? extends E> c
: 매개 변수로 넘어온 컬렉션 객체가 저장되어 있는 요소를 복사하여 ArrayList를 만든다ArrayList(int initialCapacity)
: 매개변수로 넘어온 initialCapacity 개수 만큼의 저장공간을 갖는 ArrayList를 만든다.
ArrayList에 데이터 담기
boolean add(E e)
: 매개변수로 넘어온 데이터를 가장 끝에 담는다void add(int index, E e)
boolean addAll(Collection<? extends E> c)
: 매개변수로 넘어온 컬렉션 데이터를 가장 끝에 담는다boolean addAll(int index, Collection<? extends E> c)
얕은 복사 vs 깊은 복사
ArrayList<String> list = new ArrayList<>();
list.add("A");
ArrayList<String> list2 = list;
위 코드와 같이 다른 객체에 원본 객체의 주소만을 할당하는 것은 얕은 복사 입니다. 이렇게 하면 원본 객체에서 요소가 추가되었을 때 list2 역시 반영됩니다.
반면, 객체의 모든 값을 복사하여 복제된 객체에 있는 값을 변경해도 원본에 영향을 없도록 할 때에는 깊은 복사 이며, 아래와 같이 할 수 있습니다.
ArrayList<String> list = new ArrayList<>();
list.add("A");
ArrayList<String> list2 = new ArrayList<>(list);
ArrayList<String> list3 = new ArrayList<>();
list3.addAll(list);
ArrayList에서 데이터 꺼내기
E get(int index)
int indexOf(Object o)
int lastIndexOf(Object o)
int size()
ArrayList 객체에 있는 데이터를 배열로 뽑아낼 때 다음 메소드들을 사용할 수 있습니다.
Object[] toArray()
: ArrayList 객체에 있는 값들을 Object[] 타입의 배열로 만든다<T> T[] toArray(T[] a)
: ArrayList 객체에 있는 값들을 매개 변수로 넘어온 T 타입의 배열로 만든다
단, toArray()
는 Object 타입의 배열로만 리턴하므로 제네릭을 사용하여 선언한 ArrayList 객체를 배열로 생성할 때는 <T> T[] toArray(T[] a)
를 사용하는 것이 좋습니다.
ArrayList<String> list = new ArrayList<>();
list.add("A");
String[] strList = list.toArray(new String[0]);
코드에서 new String[0]
은 의미없는 빈 배열의 타입을 넣었습니다. 왜냐하면 만약 다음과 같이 공간이 큰 배열을 넣으면 빈 공간에 null이 채워지고, 작은 경우엔 딱 그 크기만큼만 배열로 변환됩니다.
ArrayList<String> list = new ArrayList<>();
list.add("1");
String[] tempArray = new String[3];
String[] strList = list.toArray(tempArray);
for (String temp : strList) {
System.out.println("temp = " + temp);
}
// 출력 : 1 null null
ArrayList<String> list2 = new ArrayList<>();
list2.add("1");
list2.add("2");
String[] tempArray2 = new String[1];
String[] strList2 = list.toArray(tempArray2);
for (String temp : strList2) {
System.out.println("temp = " + temp);
}
// 출력 : 1
따라서 toArray()
메소드를 사용할 때엔 크기가 0인 배열로 넘겨주는 것이 좋습니다.
ArrayList에 있는 데이터 삭제
void clear()
E remove(int index)
boolean remove(Object o)
: 매개변수에 넘어온 객체와 동일한 첫 번째 데이터를 삭제한다boolean removeAll(Collection<?> c)
: 매개변수로 넘어온 컬렉션에 있는 데이터와 동일한 모든 데이터를 삭제한다
ArrayList에 있는 값 변경
E set(int index, E element)
: 지정한 위치에 있는 데이터를 두 번째 매개변수로 넘긴 값으로 변경한다. 그리고, 해당 위치에 있던 데이터를 리턴한다
ArrayList Thread safe 하게 만들기
List list = Collections.synchronizedList(new ArrayList(...));