List 자료 구조
순서가 있고, 중복을 허용하는 자료 구조를 리스트라한다.
이전까지 만든 MyArrayList
와 MyLinkedList
는 내부 구현만 다를 뿐 같은 기능을 제공하는 리스트이므로 이 둘의 공통 기능을 인터페이스로 뽑아서 추상화를 하면 다형성으로 다양한 이득을 볼 수 있다.
package collection.list;
public interface MyList<E> {
int size();
void add(E e);
void add(int index, E e);
E get(int index);
E set(int index, E element);
E remove(int index);
int indexOf(E o);
}
MyArrayList
를 활용해서 많은 데이터를 처리하는 클래스를 개발하고 있다고 가정하자. 그런데 막상 프로그램을 개발하고 보니 데이터를 앞에 추가하거나 삭제하는 일이 많으면 ArrayList
보다는 LinkedList
를 사용하는 것이 더 효율적일 것이다.
public class BatchProcessor {
private final MyArrayList<Integer> list = new MyArrayList<>(); //코드 변경
public void logic(int size) {
for (int i = 0; i < size; i++) {
list.add(0, i); //앞에 추가
}
}
}
private final MyLinkedList<Integer> list = new MyLinkedList<>();
로 변경하는 것이 더 효율적이다.BatchProcessor
는 구체적인 클래스에 의존을 하고 있어, 수정 사항이 있으면 계속 코드를 변경해야 할 수도 있다. public class BatchProcessor {
private final MyList<Integer> list;
public BatchProcessor(MyList<Integer> list) {
this.list = list;
}
public void logic(int size) {
for (int i = 0; i < size; i++) {
list.add(0, i); //앞에 추가
}
}
}
main() {
new BatchProcessor(new MyArrayList());
BatchProcessor(new MyLinkedList());
}
package collection.list;
public class BatchProcessorMain {
public static void main(String[] args) {
MyArrayList<Integer> list = new MyArrayList<>();
//MyLinkedList<Integer> list = new MyLinkedList<>();
BatchProcessor processor = new BatchProcessor(list);
processor.logic(50_000);
}
}
BatchProcessor
는 구체적인 클래스에 의존하는 것이 아닌 추상적인 List
클래스에 의존한다.BatchProcessor
코드를 전혀 변경하지 않고 원하는 리스트 전략을 런타임에 지정할 수 있다.BatchProcessor
의 외부에서 의존관계가 결정되어서 BatchProcessor
인스턴스에 들어오는 거 같아, 마치 의존관계가 외부에서 주입되는 거 같아 이를 의존관계 주입이라고 한다.new
로 생성자를 만들어서 의존관계를 주입해 생성자 의존관계 주입이라고도 한다.BatchProcessor
의 의존관계를 파악 할 수 없다BatchProcessor
에서 사용하는 리스트의 의존관계를 클래스에서 미리 결정하는 것이 아니라 런타임에서 객체를 생성하는 시점으로 미룬다.BatchProcessor
의 코드는 전혀 변경하지 않아도 된다.Collection
인터페이스는 java.utill
패키지에 있는 컬렉션 프에임워크의 일부다. List
는 객체들의 순서가 있는 컬렉션을 나타내며, 같은 객체의 중복 저장을 허용한다. 이 리스트는 배열과 비슷하지만, 크기가 동적으로 변화하는 컬렉션을 다룰 때 유리하다.
List
인터페이스는 ArrayList
,LinkedList
와 같은 여러 구현 클래스를 가지고 있으며, 각 클래스는 List
인터페이스의 메서드를 구현한다.
add(E e)
: 리스트의 끝에 지정된 요소를 추가한다.add(int index, E element)
: 리스트의 지정된 위치에 요소를 삽입한다.addAll(Collection<? extends E> c)
: 지정된 컬렉션의 모든 요소를 리스트의 끝에 추가한다.get(int index)
: 리스트에서 지정된 위치의 요소를 반환한다.set(int index, E element)
: 지정된 위치의 요소를 변경하고 이전 요소를 반환한다.remove(int index)
: 리스트에서 지정된 위치의 요소를 제거하고 그 요소를 반환한다.remove(Object o)
: 리스트에서 지정된 첫번째 요소를 제거한다.clear()
: 리스트에서 모든 요소를 제거한다.indexOf(Object o)
: 리스트에서 지정된 요소의 첫번째 인덱스를 반환한다.lastIndexOf(Object o)
: 리스트에서 지정된 요소의 마지막 인덱스를 반환한다.contains(Object o)
: 리스트가 지정된 요소를 포함하고 있는지 여부를 반환한다.sort(Comparator<? super E> c)
: 리스트의 요소를 지정된 비교자에 따라 정렬한다.subList(int fromIndex, int toIndex)
: 리스트의 일부분의 뷰를 반환한다.size()
: 리스트의 요소 수를 반환한다.isEmpty()
: 리스트가 비어있는지 여부를 반환한다.iterator()
: 리스트의 요소에 대한 반복자를 반환한다.toArray()
: 리스트의 모든 요소를 배열로 반환한다.toArray(T[] a)
: 리스트의 모든 요소를 지정된 배열로 반환한다.capacity
는 10이다.capacity
를 넘어가면 배열의 길이를 50% 증가시킨다.