본문 바로가기

JAVA/Syntax

[java.util] Collection과 Map을 이용한 정렬하기(Sort)

Collection과 Map의 종류는 다음과 같이 분류할 수 있다.




  • List 인터페이스 →  AbstractList , AbstractSequentialList , ArrayList , AttributeList , CopyOnWriteArrayList , LinkedList , RoleList , RoleUnresolvedList , Stack , Vector



  • Set 인터페이스  → AbstractSet , ConcurrentSkipListSet , CopyOnWriteArraySet , EnumSet , HashSet , JobStateReasons , LinkedHashSet , TreeSet



  • Map  인터페이스 →  AbstractMap , Attributes , AuthProvider , ConcurrentHashMap , ConcurrentSkipListMap , EnumMap , HashMap , Hashtable , IdentityHashMap , LinkedHashMap , PrinterStateReasons , Properties , Provider , RenderingHints , SimpleBindings , TabularDataSupport , TreeMap , UIDefaults , WeakHashMap


종류가... 정말 다양하다.

이 중에 생성자로 comparator값을 받는 종류가 2개 존재하는데, TreeSet과 TreeMap 이다.


TreeSet과 TreeMap은 Binary Tree (이진트리)로 객체를 정렬하여 생성시킬 수 있다. 참 좋은 클래스이다.



List부터 하나씩 설명하자.

List는 comparable한(Compare 메소드) 또는 comparator(compareTo 메소드)를 상속받아 재정의(Overridng)한 메소드를 사용한다.


거기다가 Collections.sort(); 메소드를 이용한다면, 반환값이 list가 되는데, 그러므로 3가지 결과를 확인 할 수 있다.

1. 정렬하지 않고 입력한 대로 출력하기.

2. VO에 정의한 기준으로 정렬한 후 출력하기

3. Comparator를 상속한 클래스를 기준으로 정렬한 후 출력하기.



 
               //Collections.sort();	//아얘 안쓰면, 정렬이 안됨.
		Collections.sort(list);	//이렇게 쓰면 , VO에 써준 정렬이 먹힘
		Collections.sort(list,new CustomerDecendingComparator());	
                //이렇게 쓰면, CustomerDecendingComparator가 먹힘.

 ※주의할 점은, 정렬하려고 compare메소드나 compareTo 메소드에 입력한 객체가 둘 다 같은 타입의 객체여야 한다는 것이다.


결론 : List는 어떤 List를 사용하든, List로 받으면 되기 때문에 Sort에 사용할 수 있다.


Set 같은 경우는 TreeSet만이 comparator를 상속받아서 쓰기 때문에, Set을 이용해서 정렬을 하려고 한다면 , TreeSet을 사용해야 한다.

Set을 이용하는 3가지 방법은 위와 같이

1. 정렬하지 않고 입력한 대로 출력하기.

2. VO에 정의한 기준으로 정렬한 후 출력하기

3. Comparator를 상속한 클래스를 기준으로 정렬한 후 출력하기.

이다. 그 외에 다른 Set은 정렬에 사용될 수 없다. 

실제로 구현해 보자.





2. VO에 상속받은 인터페이스 comparable을 재정의한 메소드 compareTo를 재정의한 코드이다.
	@Override
	public int compareTo(Customer o) {
		// TODO Auto-generated method stub
		
		return this.id.compareTo(o.id);
			//0이면 같은거
			//양수이면 오름차순
			//음수이면 내림차순
	}
다음과 같이 나타낼 수 있다.이 코드를 작성하고 TreeSet을 실행한다면 자동으로 compareTo 메소드를 기준으로 정렬이 이루어진다. 3. 아래 코드와 같이 ,CustomerDecendingComparator 클래스가 이름을 기준으로 내림차순정렬이 정의되어있을 때,
public class CustomerDecendingComparator implements Comparator {
	@Override
	public int compare(Customer o1, Customer o2) {
		return o1.getName().compareTo(o2.getName()) * (-1);

	}
}
생성자를 이용한 초기화를 통해 생성과 동시에 정렬기준을 처리할 수 있다.
TreeSet set = new TreeSet(new CustomerDecendingComparator());

Map을 사용하기 위해서는 TreeMap을 사용해야 한다. 그 외에는 Set과 같은 이유로 (List만 리턴 받기 때문에) 사용할 수 없다.

다만, TreeMap은 comparator를 상속받기 때문에 정렬에 사용할 수 있다.

Map은 key 값을 기준으로 정렬한다.

때문에... 위에서 제시한 방법이 통하는지는 .. 좀더 고민해보고 일단 안되는걸로 가정하고 설명한다.


TreeMap은 정렬하는 방법은 2가지이다.

1.default 값인 오름차순 정렬

2. descendingMap() 메소드를 이용한 내림차순 정렬.



		NavigableMap map2 = new TreeMap();
		map2 =  map.descendingMap();
		printMap(map2);
이렇게 NavigableMap 에 역순으로 map을 저장한다.
	public void printMap (Map map){
		Set entrys = map.entrySet();
		
		for(Object o : entrys){
			Entry entry = (Entry) o;
			System.out.println(entry.getKey()+ " : "+entry.getValue());
		}
	}

이와 같은 방법으로 Map을 나타낼 수 있다.


결론
List는 Collections.sort(list);를 이용하여 정렬시킬 수 있지만, Set과 Map은 TreeSet/ TreeMap이 아니면 정렬시킬 수 없다.

때문에 TreeSet과 TreeMap은 comparable / comparator 인터페이스를 상속받아서 정렬시켜야 하는 것이다.

comparator를 상속받아 클래스를 만들어 줘야 하는 이유는,
comparable을 상속받은 VO가 한개의 기준으로 밖에 나타낼 수 없어서 
다른 여러 기준으로 정렬을 시키려면 다른 기준을 추가해야하는데 때문에 implements comparator를 통하여
VO의 여러 속성들을 기준으로 정렬 시킬 방법들을 마련하고 나타내는 것이다.
comparator 클래스를 상속받으면 2개의 객체가 필요한 compare(Object ,Object) 메소드를 재정의 해야하고
comparable 클래스를 상속받으면 한개의 객체가 필요한 compareTo(Object anObject) 메소드를 재정의 해야 한다.

단, 비교하는 객체의 타입은 같아야 한다.




반응형