오늘은 Set 인터페이스에 대해 공부해보았다.
Set 인터페이스는 Collection 하위의 인터페이스로 중복을 허용하지 않는다.
List는 순서기반의 인터페이스지만, Set은 순서가 없다.
get(i) 메서드가 제공되지 않기 때문에 Iterator로 순회한다.
저장된 순서와 출력순서는 다를 수 있다.
아이디, 주민번호, 사번 등 유일한 값이나 객체를 관리할 때 사용한다.
HashSet, TreeSet 클래스를 예로 들 수 있다.
아래는 HashSet을 순차적으로 추출하기 위해 iterator 를 사용한 코드이다.
아래는 HashSet을 만들고 멤버를 추가하는 addMemeber 메서드와 removeMemeber를 만든 코드이다.
아래는 manager 라는 이름의 MemberHashSet 객체에 멤버들을 입력하는 코드이다.
MemeberPark2 또한 같은 키값의 다른 밸류값으로 입력해보았다.
TreeSet 클래스는
객체의 정렬에 사용되는 클래스이다.
중복을 허용하지 않으면서 오름차순이나 내림차순으로 객체를 정렬한다.
내부적으로 이진 검색 트리(binary search tree)로 구현되어있다.
이진 검색 트리에 자료가 저장될 때 비교하여 저장될 위치를 정한다.
객체 비교를 위해 Comparable 이나 Comparator 인터페이스를 구현해야 한다.
아래는 TreeSet으로 멤버를 저장할 때 비교가 불가능하여 에러가 난 모습이다.
아래와 같이 compareTo 메서드를 오버라이딩하여 비교할 수 있게 만들어줘야 한다.
이제 아이디 순서대로 출력되는 것을 볼 수 있다.
<추가공부>
자바 정렬하기 : Comparable vs Comparator
자바에서 커스텀 정렬을 할 때, 2가지 키워드가 나옵니다. Comparable하고, Comparator는 어떨 때 쓰는 것일까요? 전자는 정렬 기준을 구현하는데, 후자는 다른 기준으로 정렬하고자 할 때 사용합니다. 이것을 보면, 아니 대체 어떤 경우에 쓰는 건지 상상이 가시지 않으실 겁니다. 일단 어떠한 기준으로 sort를 한다는 게 무슨 소리인지 이해가 잘 안 가실 수도 있어요.
정렬은, 우선순위가 높은 것부터 낮은 순서대로 정렬하는 것을 의미합니다. 예를 들어서, 오름차순으로 정렬한다고 해 봅시다. 그러면, 올라가는 순서로 정렬을 할 겁니다.
그러면 우선 순위가 뭐가 더 높나요? 수가 작을 수록 더 높을 겁니다. 노란색으로 칠한 것보다, 분홍색으로 칠한 게 더 높다는 소리입니다. 따라서 기준에 맞게 sorting을 하면, 아래와 같이 나오겠네요.
오름차순으로 된 것이 맞나요? 반대로 내림차순은 어떤가요? 이것은 큰 숫자일수록 우선 순위가 높은 것입니다. 즉, 기준이 큰 순서라는 것이지요. 그러면, 아래와 같이 재배치가 되어야 할 겁니다.
기준을 정한다는 말이 조금은 와 닿으실 겁니다. 그러면 이것을 구현한다는 말은 무슨 의미일까요?
먼저, Comparable 먼저 봅시다. 필드가 x와 y만 있는 Point 클래스를 구현했다고 해 봅시다.
이것은 단순히 x와 y만을 필드로 가지고 있습니다. 이 상태에서, point 객체가 2개 들어왔다고 해 봅시다. 하나는 x의 값이 3이고, y의 값이 2입니다. 다른 하나는 x의 값이 5이고, y의 값이 2입니다. 둘의 상대적인 우선순위를 비교할 수 있나요? 없습니다.
(3,2)가 우선순위가 높은지, (5,2)가 우선순위가 높은지 알 길이 없어요. 이것은 정렬 기준이 없기 때문이에요. 이것을 만들기 위해서, Comparable을 씁니다.
Comparable<T>를 implement를 시켰는데요. compareTo를 구현해야 합니다.
이것을 어떻게 구현하면 될까요? 설명에 친절하게 나와 있습니다. 내가 this, 그러니까 자기 자신이랑 o라는 객체랑 비교했을 때, this가 o보다 우선순위가 더 높으면 -1을, 같으면 0을, 더 낮으면 1을 리턴하게 만들면 됩니다. 백준 11651번 문제에서는 y좌표는 작은 순대로, y좌표가 같다면 x좌표가 작은 순서대로 정렬하라고 했습니다.
그러면 cmp(y,o.y)의 값이 0이 아니면, 그 값을 리턴해 버리고, 같다면, cmp(x,o.x)의 값을 리턴하면 되겠네요. cmp 함수를 볼까요?
a와 b를 비교해서 a<b이면 -1을, a>b이면 1을, 같으면 0을 리턴하게 했어요. 여기까지 크게 어렵지 않아요.
그러면, Comparator는 언제 쓰면 좋을까요? 단어 정렬 문제를 봅시다.
정렬 기준
길이가 짧은 순대로, 같으면 사전 순으로 하세요.
String이 Comparable이 구현이 되어 있었던 것 같은데, 한 번 뜯어봅시다.
예상대로 있네요. Comparable<String>이. 이것을 implements를 하기 위해서는 compareTo를 구현을 해야 하는데, 이 매서드가 실제로 있는지 찾아볼까요?
있어요. 그러면 이게 어떤 기준으로 sort를 하는지 천천히 코드를 읽어 봅시다. v1은 this의 char형 배열이고, v2는 another로 들어온 string의 char형 배열입니다. lim은 this의 문자열 길이와, another의 문자열 길이 중 최솟값을 나타냅닌다.
1161번째의 while문은 이 lim만큼 돌겠다는 것을 의미하는데요. c1하고 c2가 다르다면 c1-c2를 리턴합니다. 이게 음수라면 사전순으로 앞선 건데요. 사전순으로 앞선 것이 우선순위가 높다는 것을 의미합니다. 만약에, lim만큼 돌아도 끝나지 않는 경우가 있을 겁니다. 이 때는, len이 짧은 쪽이 우선순위가 더 높을 거에요. strcmp의 수행 과정과 같다는 것을 알 수 있어요. 실제로, 그냥 Collections.sort를 시키면 아래와 같이 나온다는 것을 알 수 있어요.
중복된 것은 제거하고 출력했다는 것을 감안해 주세요. 그러면 딱 봐도 사전순으로 출력했다는 것을 알 수 있어요. 그러한가요? 문제는, 이 default 옵션하고 1181번에서 요구하는 기준하고 맞지 않다는 것입니다. 다른 정렬 기준을 만들 필요가 있어요. 이럴 때 Comparator를 이용합니다.
Comparator<T>를 implements를 시키면 compare를 구현해야 합니다. o1과 o2를 인자로 받아야 하는데요. 이 둘 중에 o1의 우선순위가 o2보다 높으면 -1을, 같으면 0을, 더 낮으면 1을 리턴하게 하면 됩니다. 길이가 작은 순으로 sort 하라고 했기 때문에, len1이 len2보다 작으면 -1을, 크면 1을 리턴하면 됩니다.
만약에 둘이 같으면 o1과 o2를 상대 비교를 하면 되는데, String의 compareTo는 o1과 o2를 비교해서, 사전순으로 앞서면 -1을 리턴합니다. 따라서, 이런 식으로 작성해 주면 되겠지요. 그 다음에 ArrayList를 정렬할 경우에는, 아래와 같이 코딩을 하면 됩니다.
arrayList 같은 경우에는, 그냥 2번째 인자에 comparator만 넣어주면 됩니다.
그러면, 제가 설정한 새로운 기준으로 sorting이 되었다는 것을 알 수 있어요. 어렵지 않아요. 커스텀 정렬은 많이 연습을 하시는 수밖에 없어요. 20번 정도 연습하시면 금방 익숙해지실 거에요. 과제 하나 드리겠습니다.
정렬 기준
문자열의 길이가 짧은 순
문자열의 길이가 같다면 사전순으로 뒤인 게 먼저 오게.
이렇게 하려면 어떻게 하면 좋을까요?
출처: https://blog.naver.com/chogahui05/221521974616
패스트캠퍼스 강의:
Java 웹 개발 마스터 올인원 패키지 Online. | 패스트캠퍼스
자바 기초문법부터 프로젝트 실습까지 Java 문법부터 스프링/스프링부트, 트렌디한 기술인 JPA까지 모두 배우는 온라인 강의입니다.
www.fastcampus.co.kr
'언어공부 > JAVA&SPRING' 카테고리의 다른 글
[패스트캠퍼스 수강 후기] 자바 인강 100% 환급 챌린지 18회차 미션 (0) | 2020.08.27 |
---|---|
[패스트캠퍼스 수강 후기] 자바 인강 100% 환급 챌린지 17회차 미션 (0) | 2020.08.26 |
[패스트캠퍼스 수강 후기] 자바 인강 100% 환급 챌린지 15회차 미션 (0) | 2020.08.24 |
[패스트캠퍼스 수강 후기] 자바 인강 100% 환급 챌린지 14회차 미션 (0) | 2020.08.23 |
[패스트캠퍼스 수강 후기] 자바 인강 100% 환급 챌린지 13회차 미션 (0) | 2020.08.22 |
댓글