2012년 10월 31일 수요일

자바의 해쉬셋(HashSet)과 연결해쉬셋(LinkedHashSet)


중복을 용납하지 않고 순서도 제멋대로인 까칠(?)한 성격의 컬렉션인 자바의 해쉬셋(HashSet)과 그래도 넣은 순서는 기억하는 연결해쉬셋(LinkedHashSet)에 대해서 살펴보는 시간을 갖도록 하겠다.^^ 계보도는 그림대로고 해쉬셋은 이름에서 알수 있듯이 Set 인터페이스를 구현하고 있다. 자세히보면 도형들의 색깔이 다른데 인터페이스와 클래스를 구분한 것이고 맨위의 Iterable은 자바의 중심인 java.lang 팩키지에 있는 인터페이스이니 궁금하면 찾아보기 바란다.ㅎㅎ


각각의 인터페이스나 클래스가 어느 팩키지에 속해있는지 궁금해하는 이들을 위해 살펴보라고 올린 그림이다. 아님 말구..ㅎㅎ 아주 간단한 예제를 통해 어떤 경우에 해시셋을 쓸수 있는지 살펴볼 것이다. 금방 끝나니 잠시만 시선을 모아주기 바란다.^^


다른건 기억하지 못하더라도 오늘 강의에서 딱 하나는 기억하기 바란다. HashSet은 중복을 허용하지 않고 들어간 순서도 제멋대로다. 오케 버뤼~ 거기까지..ㅎㅎ

해쉬셋은 이렇게 중복을 허용하지 않고 또한 순서대로 값을 다루지도 않기 때문에 임의의 숫자나 문자열을 가지고 플레이할 대상에 쓰인다. 그 예로 로또같은 복권을 들수 있지 않을까? 이번주는 당첨되려나..ㅎㅎ

예제는 크게 각각 두가지 파트로 구성하였다. 첫번째는 해쉬셋 hs 변수를 이용해서 숫자를 넣고 출력해보는 예제이고 두번째는 해쉬셋 hs2 변수를 이용해서 문자를 넣고 출력해보는 예제이다. 그리고 또한 첫번째와 두번째에 연결해쉬셋(LinkedHashSet)을 적용했다. 쉽게 구별하라고 연결해쉬셋의 변수는 기존 해쉬셋 변수앞에다가 영문자 "l"만 추가하였으니 알아보기 쉬울 것이다.


연결해쉬셋은 위의 그림이나 이름에서 알수있듯이 Set 인터페이스를 계승함과 동시에 기존 해쉬셋을 보완하는 역활을 한다. 더 자세히 설명하자면 자바4에서 등장한 연결해쉬셋(LinkedHashSet)은 해쉬셋처럼 중복은 허용하지 않지만 해쉬셋과는 다르게 요소를 넣은 순서는 기억해서 출력한다는 점이다.ㅎㅎ 무슨 얘기인지 바로바로 캐취가 안된다면 아래의 예제를 보면 다 이해가 될것이니 이제 본격적으로 예제를 들여다 보자.^^


여러분이 컬렉션의 리스트를 통해 열공(?)해 왔을터이니 Set도 그리 어렵지 않으리라 생각한다. 예제를 실행해보면 바로 내용을 알수 있도록 구성하였으니 막힘이 없을 것이다.ㅎㅎ

첫번째 구문은 숫자가 무작위로 되어있는 셋인데 여기에 중복되는 숫자들이 있다. 이것들을 넣었을때 어떻게 해쉬셋과 연결해쉬셋이 만들어지는지 보는 것이다. 두번째 구문은 숫자 대신 문자를 넣은 예제이고 역시 중복되는 알파벳을 넣었을때 어떻게 해쉬셋과 연결해쉬셋이 만들어지는지 보라고 만들었다. size( ) 메소드는 셋에 들어있는 요소들의 갯수를 보라고 만든것인데 원래셋의 요소갯수보다 작아질 것이다. 중복되는 숫자나 문자는 셋에서 제외될테니 말이다. 여기서 셋(Set)에 들어있는 요소갯수를 우리는 영어로 cardinality라고 한다. 수학이나 데이터를 다룰때 종종 나오는 단어인데 이걸 유창(?)하게 영어로 한번더 해설하자면 # of elements of the set 되시겠다. 갑자기 생각나서 써봤다. 알아두면 써먹을데가 있을 것이다.ㅎㅎ 이제 예제의 결과를 보자.^^

HashSet and LinkedHashSet={2,1,2,100,9,86}
hs size( ): 5
lhs size( ): 5
=== 강이의 JAVA강좌 ===
hs Number: 1
hs Number: 100
hs Number: 2
hs Number: 86
hs Number: 9
=== http://alecture.blogspot.com ===
lhs Number: 2
lhs Number: 1
lhs Number: 100
lhs Number: 9
lhs Number: 86

HashSet2 and LinkedHashSet2={A,B,C,A,E,D}
hs2 size( ): 5
lhs2 size( ): 5
=== 강이의 자바강좌 ===
hs2 Alphabet: D
hs2 Alphabet: E
hs2 Alphabet: A
hs2 Alphabet: B
hs2 Alphabet: C
=== http://alecture.blogspot.com ===
lhs2 Alphabet: A
lhs2 Alphabet: B
lhs2 Alphabet: C
lhs2 Alphabet: E
lhs2 Alphabet: D

결과만 봐도 예제 내용을 알수 있도록 정성아닌 정성(?)을 들였다.ㅎㅎ 결과의 처음 출력문은 해당요소들을 차례대로 관련 해쉬셋에 넣은걸 보여주는 것이고 아니다 다를까 size( ) 메소드를 이용해 체크해보니 요소갯수가 하나씩 줄었는데 결과에서 보면 숫자 2와 알파벳 A를 넣었을때 반응이 없다는걸 볼수 있을 것이다. 해쉬셋(HashSet)과 연결해쉬셋(LinkedHashSet) 모두 중복을 허용하지 않으니까 말이다.

그럼 여기서 조금 어려운 질문을 한가지 던져보겠다.ㅎㅎ 그냥 생각만 해보기 바란다. 지금 해쉬셋에 숫자 2가 두개 들어있는데 그중 하나는 2 대신에 2.00 이 들어있다고 치자. 그럼 2와 2,00을 해쉬셋에서는 같다고 취급할까 아니면 다르다고 취급할까?ㅎㅎ 재밌게도 해쉬셋에서는 이것을 다르다고 취급하여 중복을 혀용한다. 물론 우리가 상식적인 관점에서 볼때는 말이 안되더라도 말이다.^^

해쉬셋(HashSet)에서 내부적으로 중복여부를 검사할때 기본적으로 내재되어 있는 equal( ) 메소드를 통해 요소가 같은지를 체크하는데 같으면 true, 다르면 false를 돌려준다. 그런데 2와 2.00의 경우 equal( ) 메소드는 이것을 데이터형이 다를경우 다르다고 인식하기 때문에 false를 돌려준다. 하나는 int형이고 하나는 double형이고 말이다. 그래서 중복을 허용하는 이상한 사태(?)가 벌어진다. 후에 배울 트리셋(TreeSet)에서는 내부적으로 중복여부를 검사할때 기본적으로 equal( ) 메소드 대신에 compareTo( )라는 메소드를 이용한다. 이 메소드는 값의 같은지 다른지 여부에 따라 정수 -1, 0, 1을 리턴하는데 이 경우에는 0을 돌려준다. 즉 두값이 같다는 의미의 0을 돌려준다. 따라서 중복을 허용하지 않는다.^^

방금 중복여부 검사에 대해서 언급한 부분은 대부분 이해가 되지 않을 것인데 그건 너무나 당연하다. 관련 메소드에 대해서 설명한 적이 없는데 어떻게 이해를 한단 말인가? 둘다 java.lang 패키지에 들어있어 기본적으로 필요할때 자동으로 내부에서 사용되고 있는 부분인데 갑자기 이를 짚고 넘어가는 것은 나중에 여러분의 이해를 돕기위한 포석(?)으로 삼기 위함이니 그런가보다 하고 그냥 넘어가기 바란다.ㅎㅎ

그리고 해쉬셋의 경우 값 순서들도 무작위로 출력되는데 반해 연결해쉬셋은 넣은 값 순서들이 같게 출력된다는 것을 알수 있다. 그런데 여기서 한가지 의문이 생겨나는 이들이 있을 것이다. 그럼 숫자나 알파벳을 넣은 순서가 아닌 자연적으로 커지는 그냥 일반적인 순서대로 정렬하는 방법은 없을까? ㅎㅎ 물론 있다. 그건 지면할애상 다음 시간에 하려고 한다. 좀만 기다려라.ㅎㅎ HashSet과 LinkedHashSet이 이렇게 작동된다는걸 필자가 온몸으로 보여줬으니 여러분도 성의를 생각해 답만 보지말고 직접 프로그램을 만들어서 이리저리 돌려보며 해쉬셋과 연결해쉬셋에 대해서 파고들기 바란다.^^

댓글 4개:

  1. Nice blog here! Also your website lots up fast!

    What host are you the usage of? Can I get your associate link to your host?
    I want my web site loaded up as quickly as yours lol

    Here is my site: Can healing medications end up being held responsible with regard to gynecomastiadevelopment

    답글삭제
  2. ӏt's truly a nice and useful piece of information. I'm satisfied that yοu shaгed this
    useful infoгmatіon with uѕ. Ρlease stay us up to
    date lіke thіs. Thanκ уou for sharing.


    Ηere іs my wеb-site :: payday loans

    답글삭제
  3. Awesome агticle.

    Αlso ѵіѕіt my homeрage; payday loans uk

    답글삭제
  4. 미남Java프로그래머2015년 2월 6일 오전 12:50

    아 정말 감사드립니다. HashSet사용하면서 순서를 저장하지 못해 배열과 연동해서 사용하느라 코드상의 복잡함과 어려움이 많았는데 이 강의를 통해 LinkedHashSet을 배웠네요 ㅎㅎ 감사합니다 정말감사합니다

    답글삭제