1. 배열과 리스트의 차이점
- 배열 = 저장공간의 크기가 고정적
리스트 = 저장공간의 크기가 동적으로 변화
-배열의 특징
-> 크기가 7인 문자열 배열 생성과 동시에 초기화
-> 2개의 데이터를 null값으로 바꾼이후에도 크기 7
String[] array = new String[] ["가","나","다","라","마","바","사"};
array[2] = null;
array[5] = null;
System.out.println(array.length); //7
- 리스트의 특징
-> 최초 리스트 객체를 생성하면 데이터가 없으므로 저장공간의 크기 0
-> 데이터 7개 추가하면 저장 공간의 크기=7
-> 2개의 데이터 삭제하면 리스트의 저장 공간 크기는 5로 줄어들고, 인덱스 번호 또한 그에 맞게 조정
-> 데이터의 저장 공간 크기(size) = 데이터의 수
list<String> alist = new ArrayList<>();
alist.add("가");alist.add("나"); alist.add("다"); alist.add("라");
alist.add("마"); alist.add("바"); alist.add("사");
System.out.println(alist.size()); //7
alist.remove("다");
alist.remove("바");
System.out.println(alist.size()); //5
2. List<E> 객체 생성하기
- List<E>는 인터페이스이기 때문에 객체를 스스로 생성불가
-> 객체를 생성하기 위해서 List<E>를 상속받아 자식 클래스를 생성하고, 생성한 자식 클래스를 이용해 객체 생성
-But, 컬렉션 프레임워크 이용시 직접 인터페이스 구현할 필요 x
-> 컬렉션 프레임워크 안에 이미 각각의 특성 및 목적에 따른 클래스 구현돼 있음
-List<E> 인터페이스를 구현한 대표 클래스
->ArrayList<E> , Vector<E>, LinkedList<E>
1) List<E> 인터페이스 구현 클래스 생성자로 동적 클래스 객체 생성
- List<E>는 제네릭 인터페이스이므로 이를 상속한 자식 클래스들도 제네릭 클래스
- 객체를 생성할때 제네릭의 실제 타입을 지정해야함
- 기본생성자 사용
-> 기본으로 10만큼의 저장 용량 내부에 확보
- 초기 저장 용량(capacity)를 매개변수로 포함하고 있는 생성자 사용
// 다형적 표현에 따라 부모 타입인 List<E>타입으로 선언 가능
List<제네릭 타입 지정> 참조 변수 = new ArrayList<제네릭 타입지정>();
List<제네릭 타입 지정> 참조 변수 = new Vector<제네릭 타입지정>();
List<제네릭 타입 지정> 참조 변수 = new LinkedList<제네릭 타입지정>();
ArrayList<제네릭 타입 지정> 참조 변수 = new ArrayList<제네릭 타입지정>();
Vector<제네릭 타입 지정> 참조 변수 = new Vector<제네릭 타입지정>();
LinkedList<제네릭 타입 지정>참조 변수 = new LinkedList<제네릭 타입지정>();
List<Integer> aList1 = new ArrayList<Integer>(); //capacity =10
List<Integer> aList2 = new ArrayList<Integer>(30); //capacity =30
Vector<Integer>aList3 = new Vector<String>(); //capacity =10
List<MyWork> aList4 = new LinkedList<MyWork>(20); //오류 -> LInkedList는 capcity 지정불가
2) Arrays.asList() 메서드를 이용해 정적 컬렉션 객체 생성
- Arrays 클래스의 asList(T..) 정적 메서드를 사용
- 내부적으로 배열을 먼저 생성하고, 이를 List<E>로 래핑한 것
- 컬렉션 객체인데도 저장 공간의 크기를 변경 불가
- 데이터의 추가 (add()) 및 삭제(remove())불가
- 저장공간의 크기를 변경하지 않는 데이터의 변경(set())은 가능
List<제네릭 타입 지정> 참조 변수 = Arrays.asList(제네릭 타입 저장 데이터);
List<Integer> aList1 = Arrays.asList(1,2,3,4);
aList1.set(1,7); //[1,7,3,4]
aList1.add(5); //오류
aList1.remove(0); //오류
3. List<E>의 주요 메서드
구분 | 메서드명 | 기능 |
데이터 추가 | add(E element) | 매개변수로 입력된 원소를 리스트의 마지막에 추가 |
add(int index, E element) | index 위치에 입력된 원소 추가 | |
addAll(Collection<? Extends E> c) | 매개변수로 입력된 컬렉션 전체를 마지막에 추가 | |
addAll(int index, Collection<? Extends E> c) | index 위치에 입력된 컬렉션 전체를 추가 | |
데이터 변경 | set(int index, E element) | index 위치의 원솟값을 입력된 원소로 변경 |
데이터 삭제 | remove(int index) | index 위치의 원솟값 삭제 |
remove(Object o) | 원소 중 매개변수 입력과 동일한 객체 삭제 | |
clear() | 전체 원소 삭제 | |
리스트 데이터 정보추출 | get(int index) | index 위치의 원솟값을 꺼내 리턴 |
size() | 리스트 객체 내의 포함된 원소의 개수 | |
isEmpty() | 리스트의 원소가 하나도 없는지 여부를 리턴 | |
리스트 배열 변환 | toArray() | 리스트를 Obejct 배열로 변환 |
toArray(T[] t) | 입력매개변수로 전달한 타입의 배열로 변환 |
- toArray
-> 리스트를 원소의 자료형과 상관없이 Object[]로 변환
-> 특정 타입으로 변환하기 위해서는 다운캐스팅 필요
-toArray(T[] t)
->특정 타입의 배열로 리턴받기 위해서 매개변수로 특정 타입의 배열 객체를 만들어 넘겨줌
->list의 size() >= 배열의 length -> list의 크기를 지니고 있는 배열 생성
->list의 size() < 배열의 length -> 배열 length의 크기를 지니고 있는 배열 생성
4. ArrayList<E> 구현 클래스
- List<E>가 지니고 있는 특징( 데이터를 인덱스로 관리, 저장공간을 동적으로 관리) 을 그대로 지님
- ArrayList<E>의 특징
-> List<E> 인터페이스를 구현한 구현 클래스
-> 배열처럼 수집(Collect)한 원소(Element)를 인덱스(Index)로 관리하며 저장용량(Capacity)를 동적 관리
1) 데이터 추가하기 - add()
-단일 데이터 추가
- toString() -> 모든 컬렉션 구현 클래스는 이 메서드에서 모든 데이터를 한번에 정리해 출력하도록 오버라이딩
-> 생략 가능
List<Integer>aList1 = new ArrayList<Integer>(); //list<integer> 객체 생성
//add(E element)
aList.add(3);
aList.add(4);
aList.add(5);
System.out.println(aList1.toString()); //[3,4,5]
//add(int index, E element)
aList.add(1,6);
System.out.println(aList1.toString()); //[3,6,4,5]
- 컬렉션 객체 추가
-> 컬렉션 객체를 통째로 입력매개변수로 받아 추가
//addAll(Colleciton<? extends E>c)
List<Integer>aList2 = new ArrayList<Integer>();
aList2.add(1);
aList2.add(2);
aList2.addAll(aLis1); // aList = [3,6,4,5]
System.out.println(aList2.toString()); //[1,2,3,6,4,5]
//addAll(int index, Collection<? extedns E> c)
List<Integer>aList3 = new ArrayList<Integer>();
aList3.add(1);
aList3.add(2);
aList3.addAll(1,aList3);
System.out.println(aList3.toString()); //[1,1,2,2]
2) 데이터 변경하기 -set()
-데이터의 변경
-> set()메서드에서는 기존에 있는 데이터만 변경 가능
-> 없는 인덱스 위치에 값을 대입하면 IndexOutOfBoundsException 발생
//set(int index, E element) : aList3=[1,1,2,2]
aList3.set(1,5);
aList3.set(3,6);
//aList3.set(4,7)l //IndexOutOfBoundsException
System.out.println(aList3.toString()); //[1,5,2,6]
3) 데이터 삭제하기 - remove(), clear()
- 데이터 삭제
-> remove(new Integer(2)) : 정숫값 2를 원소로 갖는 객체를 지워라
-> clear() : 데이터의 개수에 관계없이 모든 데이터를 한 번에 삭제
//remove(int index) ;aList3=[1,5,2,6]
aList3.remove(1);
System.out.println(aList3.toString()); //[1,2,6]
//remove(Object o)
aList3.remove(new Integer(2));
System.out.println(aList3.toString()); //[1,6]
//clear()
aList3.clear();
System.out.println(aList3.toString()); //[}
4) 데이터 정보 추출하기 - isEmpty(), size(), get(int index)
- 데이터 정보 추출
->isEmpty() :데이터의 존재 여부, 데이터 x -> true 리턴
->size() : 저장 데이터의 개수
->get(int index) : 특정위치의 데이터값 가져오기
//isEmpty() aList3=[]
System.out.println(aList3.isEmpty()); //true
/size()
aList3.add(1);
aList3.add(2);
aList3.add(3);
System.out.println(aList3.toString()); //[1,2,3]
System.out.println("size: " +aList3.size()); //size:3
//get(int index)
System.out.println("0번째:" + aList3.get(0)); //0번째:1
System.out.println("1번째:" + aList3.get(1)); //1번째:2
System.out.println("2번째:" + aList3.get(2)); //2번째:3
for(int i=0; i< aList3.size(); i++) {
System.out.println("i번째:" +aList3.get(i));
}
5) 배열로 변환하기 - toArray(), toArray(T[] t)
//toArray() aList3 =[1,2,3]
Object[] object =aList3.toArray();
System.out.println(Array.toString(Object)); //[1,2,3]
//toArray(T[]t)
Integer[] integer1 = aList3.toArray(new Integer[0]);
System.out.println(Array.toString(Integer1)); //[1,2,3]
//toArray(T[]t)
Integer[] integer2 = aList3.toArray(new Integer[5]);
System.out.println(Array.toString(Integer2)); //[1,2,3,null,null]
5. Vector<E> 구현 클래스
import java.utill.Vector;
List<Integer>vector1 = new Vector<Integer>();
- List<E>의 공통 특징(동일 타입 수집, 메모리 동적 할당, 데이터 추가/변경/삭제 메서드) 지님
- 동기화 메서드(synchronized method)로 구현돼 있으므로 멀티 쓰레드에 적합하도록 설계
동기화 메서드
=> 하나의 공유 객체를 2개의 쓰레드가 동시에 사용할 수 없도록 만든 메서드
- 자바 API에 포함된 Vector<E>클래스
public synchronized E remove(int index) {
//...
}
public synchronized E get(int index) {
//...
}
-싱글 쓰레드에서는 ArrayList<E>를 쓰는 것이 효율적
6. LinkedList<E> 구현 클래스
import.java.util.LinkedList;
List<Integer>LinkedList = new LinkedList<Integer>();
- List<E>의 공통 특징(동일 타입 수집, 메모리 동적 할당, 데이터 추가/변경/삭제 메서드) 지님
- 싱글 쓰레드에서 사용하기 적합( 동기화 x)
- ArrayList<E>와의 차이점
1) LinkedList<E>는 저장용량을 매개변수로 갖는 생성자가 없기 때문에 객체를 생성할 때 저장용량 지정 불가
List<E> aLinkedList1 = new LinkedList<Integer>(); //o
List<E> aLinkedList1 = new LinkedList<Integer>(20); //x
2) 내부적으로 데이터를 저장하는 방식이 서로 다름
ArrayList<E> | 모든 데이터를 위치 정보(인덱스)와 값으로 저장 |
LinkedList<E> | 앞뒤 객체의 정보를 저장 모든 데이터가 서로 연결된 형태로 관리 데이터가 연속된 위치에 저장 x 데이터 부분과 주소 부분을 별도로 가지고 있음 |
7. ArrayList<E>와 LinkedList<E>의 성능 비교
구분 | ArrayList<E> | LInkedList<E> |
추가, 삭제(add,remove) | 속도 느림 | 속도 빠름 |
검색(get) | 속도 빠름 | 속도 느림 |
- ArrayList<E> 데이터 추가
-> ArrayList<E>에서 데이터를 추가하면 다른 데이터는 한칸씩 뒤로 밀려남
-> 밀려나는 모든 데이터의 위치 정보를 수정해야 한다는 것을 의미
- LinkedList<E> 데이터 추가
-> LinkedList<E>는 각 원소의 앞 뒤 객체 정보만을 저장하고 있으므로 어딘가에 값이 추가되면
값이 추가된 위치의 앞뒤 데이터 정보만 수정하면됨
-ArrayList<E> 데이터 검색
-> 데이터 자체가 인덱스 번호를 갖고 있으므로 특정 인덱스 위치의 데이터를 빠르게 찾을 수 있음
- LInkedList<E> 데이터 검색
-> 각 원소가 자신의 인덱스 정보를 따로 갖고 있지 않음
-> 앞에서부터 차례대로 번호를 세어가면서 인덱스의 위치를 찾아야함
-ArrayList<E>와 LinkedList<E>의 성능 비교
-> System.nanoTime() : 시작과 끝 시점을 측정해 그 차잇값을 나노초 단위로 읽음으로써 실행시간 계산
-> 중간 위치에 데이터를 추가 또는 삭제할 일이 많을 때는 LinkedList<E>
데이터를 검색할 일이 많을 때는 ArrayList<E> 사용이 효율적
package CollectionFramework;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class Collection1 {
public static void main(String[] args) {
//1.데이터 추가 시간 비교
List<Integer>aList = new ArrayList<>();
List<Integer>LinkedList = new LinkedList<>();
long startTime =0, endTime = 0;
//1.1 ArrayList 데이터 추가 시간
startTime = System.nanoTime();
for(int i=0; i <100000; i++) {
aList.add(0,i);
}
endTime = System.nanoTime();
System.out.println("ArrayList 데이터 추가 시간="+(endTime - startTime)+"ns");
//1.2 LinkedList 데이터 추가 시간
startTime = System.nanoTime();
for(int i=0; i <100000; i++) {
LinkedList.add(0,i);
}
endTime = System.nanoTime();
System.out.println("LinkedList 데이터 추가 시간="+(endTime - startTime)+"ns");
//2-1 ArrayList 데이터 검색 시간
startTime = System.nanoTime();
for(int i=0; i <100000; i++) {
aList.get(i);
}
endTime = System.nanoTime();
System.out.println("ArrayList 데이터 검색 시간="+(endTime - startTime)+"ns");
//2-2 LinkedList 데이터 검색 시간
startTime = System.nanoTime();
for(int i=0; i <100000; i++) {
LinkedList.get(i);
}
endTime = System.nanoTime();
System.out.println("LinkedList 데이터 검색 시간="+(endTime - startTime)+"ns");
//3-1 ArrayList 데이터 삭제 시간
startTime = System.nanoTime();
for(int i=0; i <100000; i++) {
aList.remove(0);
}
endTime = System.nanoTime();
System.out.println("ArrayList 데이터 삭제 시간="+(endTime - startTime)+"ns");
//3-2 LinkedList 데이터 삭제 시간
startTime = System.nanoTime();
for(int i=0; i <100000; i++) {
LinkedList.remove(0);
}
endTime = System.nanoTime();
System.out.println("LinkedList 데이터 삭제 시간="+(endTime - startTime)+"ns");
}
}
'Java > 문법' 카테고리의 다른 글
17 - 3장 Set<E> 컬렉션 인터페이스 (2) (2) | 2023.06.18 |
---|---|
17 -3 장 Set<E> 컬렉션 인터페이스 (1) (0) | 2023.06.16 |
17 - 1장 컬렉션 프레임워크 개념과 구조 (0) | 2023.06.16 |
16 - 5장 제네릭의 상속 (0) | 2023.06.16 |
16 - 4장 제네릭 타입 범위 제한 (0) | 2023.06.16 |