복습

자바 13일차 - 컬렉션 프레임워크(List, LinkedList, Set, HashSet, TreeSet, Comparator 본문

자바

자바 13일차 - 컬렉션 프레임워크(List, LinkedList, Set, HashSet, TreeSet, Comparator

ykm1256 2020. 4. 3. 21:45

컬렉션 프레임워크
: 자바에서 필요한 자료 구조를 미리 구현하여 java.util 패키지에서 제공하는 것

 

List 인터페이스
: 객체를 순서에 따라 저장하고 유지하는데 필요한 메서드가 정의되어 있음. 대표적으로 앞에서 사용한 ArrayList가 있고, Vector가 있다.

먼저 Member 클래스를 만들어 회원id, 회원 이름을 각각 반환하고 설정하는 함수를 구현하고, toString메서드를 재정의했다. 그리고 MemberArrayList 클래스를 만들어 Member 클래스를 ArrayList의 자료변수로 사용했다. MemberArrayList 클래스에서 멤버를 배열에 추가하는 메서드와 제거하는 메서드를 구현했고, 배열에 있는 모든 회원들의 정보를 출력하는 메서드도 구현했다. 메인함수에서 각각 4명의 정보가 들어있는 참조변수를 Member 형으로 선언하고 값을 대입해 객체를 생성했다. 그리고 각각의 객체를 ArrayList에 차례대로 넣어 출력했고, 그후에 홍길동 회원의 정보를 지우고 다시 출력했다. 결과는 대입한 순서대로 회원정보가 출력되었고, 마지막에는 홍길동 회원의 정보는 지워지고 나머지 3명의 정보만 출력된다.

*ArrayList.java 파일을 보면 객체 배열로 사용할 디폴트 용량이 10으로 정의되어 있다. 따라서 크기를 지정하지 않으면 10개짜리 배열이 생성되고, ArrayList(int)생성자를 사용하면 배열 크기를 지정할 수 있다.

 

LinkedList 클래스
: 배열에서 처음 선언한 배열의 크기 이상으로 요소가 추가되는 경우 크기가 더 큰 배열을 새로 생성하여 각 요소를 복사해야 하는 번거로움을 개선한 자료구조. 각 요소가 다음 요소를 가리키는 주소 값을 가진다. ArrayList에 비해 중간에 자료를 넣고 제거하는 데 시간이 적게 걸림.

 

LinkedList를 사용한 코드이다. LinkedList 참조변수를 만들어 차례대로 A B C를 대입한 후 출력했고, add메서드를 이용하여 인덱스 1번(2번째)자리에 D를 대입하여 값을 출력했다. 계속해서 값을 대입하고 제거하여도 다음 값의 주소값만 알고있고 실제로는 붙어있지 않아 불필요하게 새로 생성하여 복사하는 번거로움이 없다. 하지만 데이터를 검색할 때에는 처음부터 노드를 순회해야 하므로 불리한 점이 있다.

 

ArrayList로 스택 ,큐 구현하기

ArrayList를 이용하여 스택과 큐 방식을 구현했다. 먼저 일반적인 add메서드로 스택의 push를 구현했다. 그리고 remove메서드를 이용하여 pop을 구현했는데 여기서 스택은 가장 나중에 들어온 값이 먼저 제거되므로 len-1을 사용하여 가장 마지막의 값이 제거되고 반환되게 하였다.

First Input First Out 이므로 그냥 ArrayList의 add 메서드와 remove 메서드를 이용하여 쉽게 구현하였다.

 

Iterator
: 순서가 없는 Set 인터페이스를 구현한 경우에 Iterator로 요소를 순회한다.

Set 인터페이스
:  순서와 상관없이 중복을 허용하지 않는 경우에 사용하는 인터페이스 대표적으로 HashSet, TreeSet이 있다.

 

HashSet 클래스
: 집합 자료 구조를 구현하며 중복을 허용하지 않는다.

HashSet을 이용한 가장 기본적인 예제로 HashSet 참조변수를 만들고 스트링 객체를 생성하여 문자열을 차례대로 대입하였다. 결과값을 보면 중복은 허용하지 않지만 순서와 상관없이 출력된 것을 볼 수 있다.

 

HashSet 활용한 회원 관리 프로그램

앞에서 ArrayList로 구현했던 코드를 HashSet으로 바꿔서 구현하였다. 별다른 차이점은 없지만 remove 메서드에서 HashSet 클래스는 순서가 없기때문에 for문을 돌릴 수가 없다. 따라서 Iterator로 각 요소를 순회하여 값을 받아와 비교한다. 그리고 결과를 보면 ArrayList와 달리 순서대로 출력되지않는다. 또, 위의 예제에서는 중복되는 값이 자동으로 사라졌지만 이번에는 중복되는 ID가 있음에도 그대로 값이 대입되었다.
이유는 String 클래스에는 문자열을 비교하는 메서드가 미리 구현되어 있어서 문자열이 중복되면 자동으로 사라진다. 하지만 정수값인 id는 구현되어 있지않으므로 Member 클래스에서 구현해 주어야 한다.

 

회원 아이디가 같은 경우

기존의 Member 클래스에 hashCode()메서드를 회원의 id값을 반환하도록 재정의하고, equals()메서드를 memberId값을 받아와서 비교하도록 재정의 해주었다. 그 결과 중복되는 id값을 가진 회원을 등록했지만 등록되지 않았고 3명의 회원정보만 출력되었다.

*결과가 순서대로 출력되었다??

 

TreeSet 클래스
: 자료의 중복을 허용하지 않고 출력 결과 값을 정렬하는 클래스. 이진 검색 트리를 활용한다.

이진 검색 트리

: 부모-자식 노드로 구성되며 자료의 중복을 허용하지 않고, 부모가 가지는 자식 노드의 수가 2개 이하이다. 왼쪽에 위치하는 자식 노드는 부모 노드 보다 항상 작은 값을 가지고, 오른쪽 자식 노드는 항상 큰 값을 가진다.

TreeSet을 이용하여 문자열을 대입하고 결과를 출력해보았다. TreeSet 클래스를 활용했기 때문에 결과는 HashSet 과는 다르게 ㄱㄴㄷ 순서대로 출력된 것을 볼 수 있다.

 

 

TreeSet을 활용해 회원 관리 프로그램 구현

위에서 HashSet으로 구현했던 코드를 그대로 TreeSet을 써보았다. 결과는 오류가 발생했는데 읽어보면 compareTo()메서드를 구현하라는 듯 하다. 즉 정수와 문자열을 같이 대입하여 어느 것을 비교할 지 몰라서 오류가 발생했다. String 클래스에는 정렬 방식이 구현되어 있기 때문에 위의 예제에서는 알아서 정렬이 되었지만, 이번 예제는 어떤 노드를 기준으로 비교하여 트리를 형성할 지 구현하지 않아서 오류가 발생하였다.

 

Comparable 활용하기

아까 위에서 썼던 Member 클래스를 implements를 사용하여 Comparable 클래스를 받아오고 그 안에 있는 compareTo() 메서드를 회원아이디의 차를 구하도록 재정의 하였다. 결과값으로 위의 예제와 마찬가지로 트리를 형성하여 부모노드와 자식노드의 크기를 비교하여 오름차순으로 정렬되었다. 여기서 compareTo 메서드의 결과값에 -1을 곱해주거나 member.memberId-this.memberId 로 바꿔주게 되면 대소관계가 바뀌어 내림차순으로 정렬된다.

*Comparable 인터페이스는 자신과 전달받은 매개변수를 비교한다.

 

Comparator 인터페이스
: 정렬을 구현하는 인터페이스로 compare()메서드를 구현해서 사용해야 함. Comparable 인터페이스와 같은 원리로 동작하지만 Comparator 인터페이스는 두가지 매개변수를 비교한다.