Java Collection Framework : (1) List
Collection Framework
객체 배열[]
을 사용할 경우, 배열 길이는 선언과 함께 고정된다. 만약 객체가 계속 추가될 경우 배열 길이는 이를 반영하지 못한다.
또한, 배열에서 가운데에 위치한 객체를 삭제할 경우 배열은 가운데 인덱스 값이 빈 채로 계속 유지된다. 이처럼 배열은 객체의 동적 할당이 불가능하며, 메모리가 낭비될 수 있다는 단점을 가지고 있다.
이러한 단점을 보완하기 위해 Collection framework
를 사용한다. Collection
인터페이스를 implements하여 구현한 Collection framework class에는 1) List(ArrayList, LinkedList 등), 2)Set(HashSet, TreeSet 등), queue, Map이 있다.
배열(Array)의 특징
배열은 선언과 함께 길이가 고정된다. 동적 할당이 불가능하며, Index값을 기반으로 한 접근이 가능하다(for문에서 임시변수 i를 사용하여 arr[i]와 같이 접근하는 경우). 배열에는 기본 자료형(Primitive type)
과 객체
를 담을 수 있다.
List
List
는 크기가 고정되지 않으며 동적 할당이 가능하다.
만약 List에서 중간에 존재하는 값을 빼낼 경우, 리스트가 해당 값의 뒤에 있는 객체들을 앞으로 끌어와 메모리 낭비를 줄일 수 있으며(동적 할당) 배열화, 순서화, foreach method 사용과 같은 여러 방법으로 데이터에 접근 가능하다.
단, List는 객체만 다룰 수 있다(기본 자료형 사용 불가). 또한 타입 안전성을 보장하는 제네릭(generic)의 사용이 가능하다.
제네릭 타입(Generic Type)
제네릭의 경우 java 5
이후 버전부터 사용이 가능하다. 제네릭을 통해 클래스와 인터페이스, 메소드 정의 시 타입을 파라미터로 사용할 수 있다.
제네릭을 통해 1) 컴파일 시 강한 타입 체크(Strong type check) 2) 캐스팅 제거(delete Casting)가 가능하다.
이를 통해 잘못된 사용 타입으로 인한 오류를 줄이고, 따로 타입 변환을 하지 않아 프로그램 성능을 향상시킬 수 있다.
리스트는 다음과 같이 생성한다.
List<Integer> list1 = new ArrayList<>();
<>
안에 제네릭 타입을 명시할 경우, list1에는 Integer(Wrapper class 객체) 요소들만 들어가게 된다. 앞에 붙여줄 경우 뒤의 생성자에는 생략이 가능하다.
처음 new를 통해 List 객체를 생성할 때 객체의 크기는 0으로 Initializing 된다. 처음으로 add
를 통해 요소를 넣을 경우 길이는 10으로 할당되며, 이후 요소를 삽입하여 전체 길이를 모두 채웠을 때 길이/2만큼이 추가된다.
List의 경우 배열과 같이 for문을 돌며 해당 인덱스 값을 일일이 출력하지 않고, System.out.println(list1); 과 같이 List 객체만 입력해도 해당 List에 들어있는 요소들이 한 번에 출력된다.
List 주요 메소드
boolean add(generic element), void add(int index, generic element)
list 객체에 제네릭 타입 요소들을 넣어주는 메소드이다. 해당 타입 요소만을 파라미터로 받는 add(generic e)
의 경우 해당 값(e)이 list 객체에 넣어졌는지 여부를 true/false로 리턴한다.
add(int index, generic element)
를 통해 요소를 넣고 싶은 인덱스에 삽입하는 것이 가능하다. 만약 해당 인덱스 칸에 이미 다른 요소가 존재할 경우, 해당 객체는 한 칸 뒤로 밀려나게 된다.
addAll(Collection<generic> c)
, addAll(int index, Collection<generic> c)
컬렉션 객체(이 경우 리스트)를 파라미터로 받아 해당 컬렉션 객체에 들어있는 모든 값들을 현재 리스트 객체에 추가한다. index 값을 지정하여 원하는 위치에 삽입하는 것이 가능하다.
generic remove(int index) / Boolean remove(Object o)
리스트에 추가한 값을 삭제하는 메소드이다 remove(int index)는 인덱스 값을 뜻하는 숫자를 파라미터로 받아 해당 인덱스에 위치하는 index번째 요소를 삭제하고, 해당 요소값을 리턴한다. 인덱스 번호는 Array와 같이 0번부터 존재하므로, 마지막 인덱스 번호는 List 크기-1이다. remove(Object o)는 o와 같은 값을 가지는 요소를 찾아 해당 요소를 삭제하고, 삭제 성공 여부를 true/false로 리턴한다(일치하는 값이 없을 경우 false 리턴).
isEmpty()
해당 리스트가 비었는지 여부를 리턴한다. 비었을 경우 true, 값이 하나라도 들어가 있으면 false를 리턴한다.
contains(Object o), containsAll(Collection c)
리스트 객체가 o와 일치하는 값을 가지고 있는지 여부를 리턴한다. 리스트 객체에 해당 값이 있을 경우 true, 없으면 false를 리턴한다. containsAll의 경우 파라미터로 받는 컬렉션 객체(이 경우에는 리스트)에 들어있는 요소들을 모두 가지고 있는지 여부를 판단한다.
clear()
리스트 객체에 들어있는 모든 요소들을 삭제한다.
retainAll(Collection c)
파라미터로 받는 컬렉션 객체와 현재 객체의 교집합 값을 현재 객체에 추가한다. 이 경우 기존에 있는 값은 모두 사라지고 교집합 값만이 존재하게 된다. 이후 add를 통해 다른 값의 추가도 가능하다.
size()
리스트 객체 크기(길이)를 리턴한다.
get(int i)
i번째 인덱스에 위치한 요소를 가져온다.
charAt(int index)
현재 객체의 index번째에 위치한 문자를 리턴한다. 문자/문자열 객체만 사용 가능하다.
startsWith(String str)
파라미터로 받는 문자열 str로 시작하는 String 객체인지 여부를 리턴한다.
List의 오름차순/내림차순 정렬
sort()
메소드를 통해 리스트 내부 요소들의 정렬이 가능하다.
list5.sort(Comparator.naturalOrder());
System.out.println("오름차순 list5 : " + list5); // 오름차순 정렬
list5.sort(Comparator.reverseOrder());
System.out.println("내림차순 list5 : " + list5 ); // 내림차순 정렬
List 객체에서 특정 조건을 만족하는 문자열 찾기
1) charAt(int index)
if(element.charAt(0) == 'b') // 첫 번째 문자열이 b인 문자열 객체인지 여부 확인
System.out.println(element);
만약 문자열 객체 element의 0번째에 위치한 문자가 b일 경우 element를 출력한다.
2) startsWith(String str)
if(element.startsWith("heejin"))
System.out.println(element); // "heejin"으로 시작하는 문자열이면 element 출력
3) 향상 for문 사용하기(enhanced for)
for(String element : list) {
// for문을 돌며 list 요소들을 하나씩 꺼내 element에 넣는다.
if(element.startsWith("b")) {
System.out.println(element);
list.remove(element); // 조건을 만족할 경우 해당 요소를 출력 후 리스트에서 삭제한다.
} // for문을 돌리며 remove 시 syntax 에러는 없지만 돌리면 perspective 뜸(에러)
}
System.out.println(list);
+) List 객체는 루프(for문, if문 등)를 돌리면서 요소를 제거할 경우 에러가 발생한다. (for문의 경우 문법 오류는 뜨지 않지만 실제 컴파일 시 제대로 동작하지 않는다)
따라서 해당 리스트 객체를 읽어오는 Iterator
객체를 사용하여 요소를 제거해야 한다.
Iterator 객체로 리스트 객체 요소 삭제하기
List<String> list2 = new ArrayList<>();
list2.add("aaa");
list2.add("bbb");
list2.add("ccc");
list2.add("ddd");
Iterator<String> iter = list2.iterator();
// list2를 읽어오는 Iterator 객체 iter 생성. 이 경우 iter의 제네릭 타입은 List객체 타입과 동일해야 한다.
while(iter.hasNext()) {
String element = iter.next();
if(element.startsWith("b"))
iter.remove();
// Iterator는 다음 값을 next() 메소드를 통해 미리 보고, 조건을 만족할 경우 해당 값을 삭제한다.
// Iterator 객체를 통해 remove 시 hasNext()는 b로 시작하는 노드의 다음 노드를 가리키며 에러가 발생하지 않는다.
}
System.out.println(list2);
// 정상 출력. 따라서 루프문을 도는 도중 객체값을 삭제하고 싶으면 Iterator를 사용
//주어진 배열을 List에 중복 없이 넣은 후 순차 정렬해서 출력하기
int[] arr = { 102, 32, 32, 65, 29, 236, 5, 44, 82, 52, 70, 52};
List<Integer> list1 = new ArrayList<>();
// java.util의 List를 추가해야 한다!(awt 추가하면 오류)
for(int i=0; i<arr.length; i++) {
if(list1.contains(arr[i]) == false)
list1.add(arr[i]);
/*
내코드
list1.add(arr[i]);
if(list1.contains(arr[i]))
list1.remove(i); // list1에 arr값을 모두 넣은 후, if문을 사용하여 list에 이미 해당 값이 있을 경우 i번째 (=현재) 인덱스 값을 지운다.
이 경우 perspective 열림 왜열리는지 궁금허네.. -> Iterator 객체를 사용하지 않고 루프를 돌면서 remove 시 에러.
따라서 중복값이 없을 때만 list에 추가시키는 구조로 코드를 바꿔준다.
*/
}
Author And Source
이 문제에 관하여(Java Collection Framework : (1) List), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@soir/Java-Collection-Framework-1-List저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)