Java :: Collection :: 1.2 ArrayList

김병철·2022년 8월 31일
0

Java

목록 보기
2/20

Java의 정석 3판을 보며 공부한 내용을 정리하였습니다.
남궁성님께 많이 배우고 있습니다.

1.2 ArrayList

가장 많이 사용되는 컬렉션 클래스로
ArrayList 역시 List! 이므로 순서가 있고 중복 허용!

ArrayList는 Vector를 개선한 것으로 구현원리와 기능이 동일하다.
Vector는 기존에 작성된 소스와의 호환성을 위해 남겨놓았을 뿐!
가능하면 ArrayList를 사용하자!

ArrayList는 Object배열을 이용하여 데이터를 순차적으로 저장한다.

순차적 저장?
첫 번째로 저장 -> 0 번 인덱스에 데이터 저장
두 번째로 저장 -> 1 번 인덱스에 데이터 저장
세 번째로 저장 -> 2 번 인덱스에 데이터 저장
... 쉽죠?

배열에 더 이상 저장할 공간이 없으면 더 큰 길이의 배열을 생성해야 했다.
하지만 ArrayList는 Object 배열의 장점은 자동으로 길이를 늘려준다는 점이다!
매우 편리하고 길이를 신경 쓸 필요가 없겠네??

# 여기서 짚고 넘어갈 점!

자동으로 처리를 해줘서 아무렇지 않게 쓰면 될 것 같지만!
이 과정에서 처리시간이 많이 소요되므로
ArrayList를 배열과 똑같이 생성할 때 저장할 요소의 개수를 고려해서 실제 저장할 개수보다 약간 여유있는 크기로 해야 한다.

또한, ArrayList와 Vector같이 배열을 이용한 자료구조는 순차적으로 데이터를 읽고 저장하는 속도는 빠르지만, 길이를 변경하거나 중간에 삽입과 삭제를 하는 경우에는 속도가 느리다.
(삽입, 삭제가 이루어졌을 때 뒤의 객체를 앞으로 당겨야 하므로 느리다)


ArrayList의 생성자와 메서드

  • ArrayList()
    -> 크기가 10인 ArrayList 생성
  • ArrayList(Collection c)
    -> 주어진 컬렉션이 저장된 ArrayList 생성
  • ArrayList(int initialCapacity)
    -> 지정된 초기용량을 갖는 ArrayList 생성
  • boolean add(Object o)
    -> ArrayList의 마지막에 객체 추가. 성공하면 true
  • void add(int index, Object element)
    -> 지정된 위치(index)에 객체 저장
  • boolean addAll(Collection c)
    -> 주어진 컬렉션의 모든 객체 저장
  • boolean addAll(int index, Collection c)
    -> 지정된 위치부터 주어진 컬렉션의 모든 객체 저장
  • void clear()
    -> ArrayList를 완전히 비움
  • Object clone()
    -> ArrayList 복제
  • boolean contains(Object o)
    -> 지정된 객체(o)가 ArrayList에 포함되어 있는지 확인
  • void ensureCapacity(int minCapacity)
    -> ArrayList의 용량이 최소한 minCapacity가 되도록 한다.
  • Object get(int index)
    -> 지정된 위치에 저장된 객체 반환
  • int indexOf(Object o)
    -> 지정된 객체가 저장된 위치를 찾아 반환
  • boolean isEmpty()
    -> ArrayList가 비어있는지 확인
  • Iterator iterator()
    -> ArrayList의 Iterator객체 반환
  • int lastIndexOf(Object o)
    -> 객체(o)가 저장된 위치를 끝부터 역방향으로 검색해서 반환
  • ListIterator listIterator()
    -> ArrayList의 ListIterator를 반환
  • ListIterator listIterator(int index)
    -> ArrayList의 지정된 위치부터 시작하는 ListIterator를 반환
  • Object remove(int index)
    -> 지정된 위치에 있는 객체 제거
  • boolean remove(Object o)
    -> 지정한 객체 제거. 성공하면 true, 실패하면 false
  • boolean removeAll(Collection c)
    -> 지정한 컬렉션에 저장된 것과 동일한 객체들을 ArrayList에서 제거
  • boolean retainAll(Collection c)
    -> ArrayList에 저장된 객체 중에서 주어진 컬렉션과 공통된 것들만 남기고 나머지 삭제
  • Object set(int index, Object element)
    -> 주어진 객체(element)를 지정된 위치에 저장
  • int size()
    -> ArrayList에 저장된 객체의 개수 반환
  • void sort(Comparator c)
    -> 지정된 정렬기준(c)으로 ArrayList 정렬
  • List subList(int fromIndex, int toIndex)
    -> fromIndex부터 toIndex사이에 저장된 객체 반환
  • Object[] toArray()
    -> ArrayList에 저장된 모든 객체들을 객체배열로 반환
  • Object[] toArray(Object[] a)
    -> ArrayList에 저장된 모든 객체들을 객체배열 a에 담아 반환
  • void trimToSize()
    -> 용량을 크기에 맞게 줄인다.(빈 공간을 없앤다.)

기본 메서드들 사용 예

ArrayList(), add(), subList(), sort(), containsAll(), retainAll()

...

public static void main(String[] args){		// 메인함수 시작
	ArrayList list1 = new ArrayList(10);	// ArrayList 선언 및 할당(길이는 10)

	list1.add(new Integer(3));				// list1에 Integer객체 값(4) 추가
	list1.add(new Integer(2));
	list1.add(new Integer(1));
    list1.add(new Integer(5));
	list1.add(new Integer(9));
    list1.add(new Integer(6));
	list1.add(new Integer(8));
    list1.add(new Integer(7));
	list1.add(new Integer(4));
    
    ArrayList list2 = new ArrayList(list1.subList(2, 5));    
	
    System.out.println("list1 : "+list1);
	System.out.println("list2 : "+list2);
    System.out.println();
    
    Collections.sort(list1);		// list1과 list2를 정렬
	Collections.sort(list2);		//
	System.out.println("list1 : "+list1);
	System.out.println("list2 : "+list2);
    System.out.println();
    
    System.out.println("list1.containsAll(list2) : "+list1.containsAll(list2));
		
	list2.add("B");
	list2.add("C");
	list2.add(3, "A");
	System.out.println("list1 : "+list1);
	System.out.println("list2 : "+list2);
    System.out.println();
    
    list2.set(3, "P");
	System.out.println("list2 : "+list2);
    System.out.println();
    
    // list1에서 list2와 겹치는 부분만 남기고 나머지 삭제한 결과는 true
    System.out.println("list1.retainAll(list2) : "+ list1.retainAll(list2));
	System.out.println("list1 : "+list1);
	System.out.println("list2 : "+list2);
    System.out.println();
    
    // list2에서 list1에 포함된 객체 삭제
	for(int i=list2.size()-1;i>=0;i--) {
		if(list1.contains(list2.get(i))) {
			list2.remove(i);
		}
	}
    System.out.println("list1 : "+list1);
	System.out.println("list2 : "+list2);
    
}

출력 결과 :

list1 : [3, 2, 1, 5, 9, 6, 8, 7, 4]
list2 : [1, 5, 9]

list1 : [1, 2, 3, 4, 5, 6, 7, 8, 9]//정렬된 모습
list2 : [1, 5, 9]

list1.containsAll(list2) : true//list1이 모든 요소(1, 5, 9)를 포함해서 true
list1 : [1, 2, 3, 4, 5, 6, 7, 8, 9]
list2 : [1, 5, 9, A, B, C]//B, C를 추가하고 3번인덱스에 A추가

list2 : [1, 5, 9, P, B, C]//3번 인덱스가 P로 변경

list1.retainAll(list2) : true//list1에 변화가 있어서 true
list1 : [1, 5, 9]//list1에서 list2와 공통되지 않은 것 전부 삭제
list2 : [1, 5, 9, P, B, C]

list1 : [1, 5, 9]
list2 : [P, B, C]//list2에서 list1과 공통되지 않은 것 전부 삭제

위 예제에서 확인할 것

  • 순서가 유지된다는 것.
  • sort()로 정렬된 것. (정렬 방법은 다시 확인해야 함. 일단은 '아 정렬했구나' 정도만!)
  • for문의 초기식과 조건식 확인할 것
for(int i=list2.size()-1;i>=0;i--) {
	if(list1.contains(list2.get(i))) {
		list2.remove(i);
	}
}

순서가 있는 List라서 하나가 삭제될 때마다 객체가 하나씩 앞으로 당겨지므로 i가 하나씩 증가하면 올바른 위치에 접근할 수 없다.
그러므로 뒤에서부터 삭제해야 한다.


긴 문자열을 원하는 길이로 잘라서 ArrayList에 담는 예제

...

public static void main(String[] args) {
	final int SLICE = 5;		// 자르는 단위
	String src = "0123456789abcdefghjikl";
			
	int len = src.length();
	
	List list = new ArrayList(len/SLICE+5);	// 여유롭게 길이 설정
	
	for(int i=0; i<len; i+=SLICE) {
		if(i+SLICE < len) {
			list.add(src.substring(i, i+SLICE));
		}
		else {
			list.add(src.substring(i));
		}
	}
	
	for(int i=0; i<list.size(); i++) {
		System.out.println(list.get(i));
	}
}

출력 결과 :

01234
56789
abcde
fghji
kl

문자열에서 charAt()을 써서 잘라 담는 것과 ArrayList의 메서드를 사용하는 것과의 차이를 확인할 수 있다.
(얼마나 간단해 지는지)

profile
keep going on~

0개의 댓글