(JAVA) ArrayList, LinkedList
컬렉션의 전반적인 설명은 아래 링크를 참고하자.
https://acid7937.tistory.com/37
다들 배열을 기억할 것이다. 배열의 규칙에 대해 다들 잘 알겠지만. 예시로
숫자 5개를 입력하고 싶을때.
int[] arr = {1,2,3,4,5};
for (int number : arr)
{
System.out.print(number + "\t");
}
뭐... 이렇게 5개를 사전에 입력해서 사용해도 괜찮지만. 내가 프로그램 실행해서 직접 입력하고 싶다면? 여기서 뭘 어떻게 할것인가? 이것말고 new 써서 초기화한뒤 배열 크기 지정 하는걸 알 것이다.
Scanner scan = new Scanner(System.in);
int count=1;
int[] arr1 = new int[5];
for(int i=0; i<arr1.length; i++){
System.out.printf("%d 번째 숫자 입력 : ",count);
count++;
arr1[i] = scan.nextInt();
}
for (int number2 : arr1){
System.out.print(number2+ "\t");
}
내가 입력한 결과는 다음과 같다.
1 번째 숫자 입력 : 4
2 번째 숫자 입력 : 3
3 번째 숫자 입력 : 6
4 번째 숫자 입력 : 7
5 번째 숫자 입력 : 7
4 3 6 7 7
Process finished with exit code 0
간단하게 배열 5칸을 만들어서 숫자를 입력해 주었다.
그런데 내가 프로그램 열어서 수정없이 5개말고 10개 입력하고 싶다면?
자 이젠 컬렉션을 기억해 보자.
List가 무엇인가?
순서 O 중복 O 였던게 기억 나는가?
이건 마치 배열같다...
ArrayList를 먼저 살펴보자.
ArrayList 예제를 만들었는데 위와 이해하기 쉽게 비슷한 구조로 만들었다 코드로 살펴보자.
ArrayList arr2 = new ArrayList();
Scanner sc = new Scanner(System.in);
for(;;){
arr2.add(sc.next());
if(arr2.contains("STOP")){
break;
}
}
arr2.remove("STOP");
System.out.println(arr2);
배열에 계속 값을 집어 넣는데 STOP 이라는 문구를 입력 받으면 멈추게 만들고 배열을 출력 하도록 했다. 결과는 다음과 같다.
54
31
5
98
HAHA
hehe
C
+
1
-5
STOP
[54, 31, 5, 98, HAHA, hehe, C, +, 1, -5]
힘의 차이가 느껴지는가? 어떤 타입을 넣어도 값이 들어가고 배열의 크기를 설정하지 않아도 된다.
그런데 이게 싫으면 제네릭을 사용해도 된다.
ArrayList<Integer> arr2 = new ArrayList();
Scanner sc = new Scanner(System.in);
for(;;){
arr2.add(sc.nextInt());
if(arr2.contains(-1)){
break;
}
}
arr2.remove(Integer.valueOf(-1));
System.out.println(arr2);
}
}
위의 코드는 제네릭으로 인하여 Integer만 입력이 가능하다. 이번에는 -1을 입력 받으면 종료하고 입력된 배열을 보여주는 기능을 만들었다.
출력 결과는 다음과 같다.
54
62
19
2
-1
[54, 62, 19, 2]
이처럼 기존 배열보다 다양한 기능을 손쉽게 사용할수 있다.
다음으로 LinkedList를 알아보자.
LinkedList<Integer> arr2 = new LinkedList();
Scanner sc = new Scanner(System.in);
for(;;){
arr2.add(sc.nextInt());
if(arr2.contains(-1)){
break;
}
}
arr2.remove(Integer.valueOf(-1));
System.out.println(arr2);
}
}
ArrayList를 그냥 LinkedList로 변경하였다. 출력 결과는 다음과 같다.
51
21
34
1
-1
[51, 21, 34, 1]
의문이 들것이다. 아니 사용법이 같으면 뭣하러 이렇게 나누나 List 하나만 만들어서 쓰면 되지.
---------------------------------------------------------------------------------------------------------------------------------------------------
사실 컬렉션의 기능들은 단순 다른 자바 기초 언어들 처럼 사용할수도 있지만 이전 게시글에도 언급하였듯.
컬렉션은 자료구조를 위해 대부분 사용이 된다.
자료구조라는게 말이 어려워 보이지 그냥 값의 저장 방식이다. 그리고 이건 프로그램 성능에 영향을 미친다.
둘을 비교해 보자.
ArrayList
ArrayList는 긴 막대기라고 생각하자. 거기에 아래서부터 차례로 줄그어서 숫자를 하나씩 써 보았다.
다른 말로, 주소값 하나를 받으면 그 안에 순차적으로 데이터를 우겨 넣는다.
1 | 2 | 3 | 4 | 5 | 6 | 7 |
장점은 무엇일까?
위치가 순차적으로 고정되어 있어서 뭐가 어디에 있는지 더욱 빠르게 찾을수 있다. 우리도 물건 찾을때 어느 서랍에 있는지 알면 바로 찾을 것이다.
다만 단점도 있다.
내가 만약 중간에 값을 하나 추가하거나 삭제 한다면? 방금 ArrayList는 막대기와 같은 녀석이라고 했다. 그럼 무슨일이 발생할까.
가운데 3을 지워보자.
1 | 2 | 4 | 5 | 6 | 7 |
이난리가 난다.
즉, 뒤의 값들을 복사 한다음에 싹다 붙여넣기를 한다. 그럼 어떻게 될까? (지우개로 뒤를 다 지우고 새로 쓴다고 생각하자)
속도가 느리다. 즉, ArrayList는 중간에 값의 추가 제거가 있다면 부적합하다.
LinkedList
이녀석의 특징은 값들이 각자 하나씩 자신의 주소값을 가지고 있으며 바로 앞의 값만 참조한다. 무슨 말일까
1 | 2 | 3 | 4 | 5 | 6 | 7 |
1,2,3,4,5,6,7 이게 전부 각자 하나의 막대기 이다. 그러니깐 ArrayList는 하나의 막대기 LinkedList는 작은 막대기들의 모임. 이라고 생각하자.
이번에도 3을 날려보자.
1 | 2 |
4 | 5 | 6 | 7 |
(표를 옆에다 붙이는걸 못하겠다... 아쉽다...2랑 4랑 이어져 있는거임)
그림이 이상해 졌지만 각자의 주소값들을(막대기들을) 우리는 노드 라고 부르는데 각 노드들은 바로 앞의 노드들이랑만 이어져 있다.
이런식으로 되어있다. 해서 중간에 하나 삭제해도 바로 앞에것을 연결해 버린다.
그래서 위의 설명처럼 LinkedList의 장점은 중간에 추가 삭제가 있어도 복사 붙여넣기 이런거 없이 그냥 똑깍 하고 끼우면 된다. 그러면 ArrayList 보다는 처리 시간이 빠를것이다.
하지만 이놈들은 각자 주소값을 가지고 있고 각 노드들이 바로 앞의 값만 참조하고 있기에 내가 특정 값을 찾기를 원하면 앞에서 부터 다 훑어 버린다.
무슨 말이냐면 ArrayList는 이미 뭐가 어디에 있는지 알고 있는데.(데이터 이동이 없으니)
(숫자3 어딨냐?
ArrayList : 2번 배열에 있어.
LinkedList는 모른다. 그래서 하나하나 노드들 끼리 스캔해서 노가다해서 찾아야 한다.
(숫자 3 어딨냐?
첫번째 노드 : 음 나는 아니군 두번째야 너 3 가지고 있냐?
두번쨰 노드 : 음 나도 아니군 세번째야 너 3 가지고 있냐?
세번째 노드 : 오 나 가지고 있음.
)
결론은 우리가 값을 중간에 추가 변경 할 일이 없다면 프로그램 만들때 ArrayList를 사용해 주고.
프로그램 특성이 우리가 중간에 값을 추가 변경 해야 된다면 LinkedList로 코딩하는게 바람직 하다.