컬렉션 프레임워크1: Set과 List계열 예시위주

컬렉션 프레임워크1: Set과 List계열 예시위주

Collections 프레임워크




Collections 인터페이스의 메서드

  • Collections 인터페이스는 List와 Set계열의 공통 조상으로 아래 메서드 사용가능
  • 아래 메서드들 중 index사용하는 메서드는 set계열에서 사용할 수 없다.
    • WHY? set은 index가 없기때문에!

https://bombichun.tistory.com/entry/JAVA%EC%BB%AC%EB%A0%89%EC%85%98-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8Dcollections-framework




List와 Set 특징비교

계열 특징 방법
List 중복가능 데이터가 중복되어도 index로 구분함
각 요소접근 index사용하면 됨
데이터조회 indexOf()로 위치찾기가능, contains()로 데이터유무(boolean) 확인가능
데이터수정 set()
정렬 sort()
set 중복불가능 중복데이터제거를 위해 @Override hashcode()와 equals() 재정의필수
각 요소접근 index 정렬불가능-> iterator객체의 hasNext(), next()사용
데이터조회 contains()로 데이터유무(boolean) 확인가능, for(Object obj : hashset명 ){ System.out.println(obj)}
데이터수정 인덱스가 없어서 데이터수정없음불가능 -> 걍 삭제(remove) 후 추가(add)
정렬 index없어서 sort()사용불가 -> TreeSet<>이용




List계열 : ArrayList와 LinkedList 성능차이

  • ArrayList 단점 : 비순차적인 데이터의 추가, 삭제에 많은 시간이 걸림
  • 이를 해결하기 위해 LinkedList가 있음
  • LinkedList 특징 :
    • 각 요소를 Node(노드)로 정의.
    • Node는 다음요소의 참조값과 데이터로 구성됨.
    • 각 노드는 링크정보를 가지므로 ㅔ이터를 연속으로 구성할 필요가 없음.
    • 따라서 ArrayList가 전체전익 요소를 움직였던 것에 비해 훨씬 가볍게 작동함.
  • 그렇다면 ArrayList와 LinkedList 데이터처리과정별 성능차이는 어떨까?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
	private static void addTest(String testcase, List<Object> list){
long start = System.nanoTime();
for(int i=0; i<1000000; i++){
list.add(new String("Hello"));
}
long end = System.nanoTime();
System.out.println(testcase+" 소요시간: "+(end-start));
}

private static void addTest2(String testcase, List<Object> list){
long start = System.nanoTime();
for(int i=0; i<100000; i++){
list.add(0, new String("Hi"));
}
long end = System.nanoTime();
System.out.println(testcase+" 소요시간: "+(end-start));
}
private static void accessTest(String testcase, List<Object> list){
long start = System.nanoTime();
for(int i=0; i<100000; i++){
list.get(i);
}
long end = System.nanoTime();
System.out.println(testcase+" 소요시간: "+(end-start));
}



public static void main(String[] args) {
ArrayList<Object> alist = new ArrayList<Object>();
LinkedList<Object> list = new LinkedList<Object>();

addTest("순차적 추가: ArrayList", alist);
addTest("순차적 추가: LinkedList", list);
addTest2("중간에 추가: ArrayList", alist);
addTest2("증간에 추가: LinkedList", list);
accessTest("데이터접근: ArrayList", alist);
accessTest("데이터접근: LinkedList", list);
}

//출력값
순차적 추가: ArrayList 소요시간: 37748800
순차적 추가: LinkedList 소요시간: 85107500
중간에 추가: ArrayList 소요시간: 15683133500
증간에 추가: LinkedList 소요시간: 3635400
데이터접근: ArrayList 소요시간: 2516900
데이터접근: LinkedList 소요시간: 7363336600




List계열 : ArrayList<> 로또게임 예시

  • 로또는 1부터 45까지의 숫자가 적힌 공 중에서 당첨공 6개와 보너스공 1개를 랜덤으로 뽑는다.
  • 이 공들은 중복을 허용하지않는다.
  • List는 중복을 허용하는 계열인데 어떻게하면 로또를 만들 수 있을까?
    • contains()로 중복확인가능
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class ListLotto{
Integer bonus;
List<Integer> lotto = new ArrayList<>();

public void setup(){
Random rd = new Random();
while(bonus == null){
int num = rd.nextInt(45)+1;
if(!lotto.contains(num)){
if(lotto.size() < 6){
lotto.add(num);
}else{
bonus = num;
}
}
Collections.sort(lotto);
}

}
@Override
public String toString() {
return "당첨번호: "+lotto+", 보너스: "+bonus;
}

}

public class ListLottoTest {

public static void main(String[] args) {
ListLotto lotto = new ListLotto();
lotto.setup();
System.out.println(lotto);
}

}




Set계열 : TreeSet<> 정렬

  • set계열을 정렬하기만 원한다면 TreeSet<>안에 넣기만 하면 됨.
  • TreeSet<>은 add()가 안됨 -> 내부적으로 알파벳오름차순인데 객체가 add되면 비교가 불가능함.
  • Treeset<>()에서 괄호안에 정렬기준을 추가할 수 있다.
    • Treeset<>(new StringLengthComparator()) : StringLength를 기준으로 짧은 String이 앞쪽으로 정렬된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) {
TreeSet<Object> set = new TreeSet<>();

set.addAll(Arrays.asList("w","a","t","e","r"));
//set.add(3); //exception: cannot be cast to java.lang.Integer Object타입이 들어올 수 있지만 add할때는 동일한 데이터들을 넣어줘야 TreeSet이 비교할 수 있다
//set.add(Arrays.asList("삼","다","수")); //exception : cannot be cast to java.lang.Comparable
System.out.println("자동으로 오름차순: "+set);
System.out.println("처음 요소: "+set.first());
System.out.println("마지막 요소: "+set.last());
System.out.println("a 아래 요소: "+set.lower("a")); //최하위계증.알파벳순으로 a는 가장먼저이기때문에 최하위계층
System.out.println("z 다음 요소: "+set.higher("z")); //최상위계층.알페벳순으로 z는 가장마지막이기때문에 최상위계층
System.out.println("e 다음 요소: "+set.higher("e"));

NavigableSet<Object> naviSet = set.descendingSet();
System.out.println("내림차순 : "+naviSet);
}




Set계열 : TreeSet<> 로또게임 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class TreesetLotto{
Integer bonus;
Set<Integer> lotto = new TreeSet<>();

public void setup(){
Random rd = new Random();
while(bonus == null){
int num = rd.nextInt(45)+1;
if(lotto.size() < 6){
lotto.add(num);
}else{
bonus = num;
}
}
}

@Override
public String toString() {
return "당첨번호: "+lotto+", 보너스: "+bonus;
}
}

public class TreeSetLottoTest {
public static void main(String[] args) {
TreesetLotto lotto = new TreesetLotto();
lotto.setup();
System.out.println(lotto);
}
}
//출력값
당첨번호: [5, 14, 23, 29, 33, 38], 보너스: 31