๐Ÿ“‚ JAVA/์ฃผ์š” ๊ฐœ๋…

Comparable๊ณผ Comparator

Amenable 2023. 1. 28. 23:05
public class Main {
  public static void main(String[] args) {
    char[] chArr = {'E', 'D', 'C', 'B', 'A'};
    
    System.out.println("์ •๋ ฌ ์ „ : " + Arrays.toString(chArr));
    
    Arrays.sort(chArr);
    System.out.println("์ •๋ ฌ ํ›„ : " + Arrays.toString(chArr));
  }
}
// ์ •๋ ฌ ์ „ : [E, D, C, B, A]
// ์ •๋ ฌ ํ›„ : [A, B, C, D, E]

  Arrays.sort๋ฅผ ์ด์šฉํ•˜๋ฉด ์œ„์™€ ๊ฐ™์ด ์ •๋ ฌ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ •๋ ฌ์ด ๊ฐ€๋Šฅํ•œ ์ด์œ ๋Š” Comparable์„ ๊ตฌํ˜„ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ด๋ฒˆ ๊ธ€์—์„œ๋Š” 'Comparable๊ณผ Comparator์˜ ๊ฐœ๋…', '๊ฐ๊ฐ์˜ ์‚ฌ์šฉ๋ฒ•', '์ต๋ช… ํด๋ž˜์Šค๋ฅผ ํ™œ์šฉํ•œ ํŽธ๋ฆฌํ•œ Comparator ์‚ฌ์šฉ๋ฒ•'์„ ์•Œ์•„๋ณด๋„๋ก ํ•˜์ž.

 

1. Comparable๊ณผ Comparator ๐ŸŸ

  Comparable๊ณผ Comparator๋Š” ์ปฌ๋ ‰์…˜์„ ์ •๋ ฌํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•˜๊ณ  ์žˆ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋‹ค. Comparable์€ ๊ธฐ๋ณธ ์ •๋ ฌ๊ธฐ์ค€์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, Integer์™€ ๊ฐ™์€ wrapperํด๋ž˜์Šค์™€ String, Date, File๊ณผ ๊ฐ™์€ ํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค๋ผ๋ฆฌ ์„œ๋กœ ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋Š” ํด๋ž˜์Šค๋“ค์ด Comparable์„ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋‹ค. (์•„๋ž˜๋Š” String๊ณผ Integer์˜ declaration ์ค‘ ์ผ๋ถ€๋ถ„์ด๋‹ค.)

public final class String implements Comparable<String> {
}

public final class Integer implements Comparable<Integer> {
}

  Comparator๋Š” ๊ธฐ๋ณธ ์ •๋ ฌ๊ธฐ์ค€ ์™ธ์— ๋‹ค๋ฅธ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•˜๊ณ ์ž ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. Comparable์„ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค๋“ค์ด ๊ธฐ๋ณธ์ ์ธ ์ •๋ ฌ ๊ธฐ์ค€์ด ์•„๋‹Œ, ๋‚ด๋ฆผ์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌํ•œ๋‹ค๋˜๊ฐ€ ๋‹ค๋ฅธ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•˜๊ณ  ์‹ถ์„ ๋•Œ Comparator๋ฅผ ๊ตฌํ˜„ํ•ด์„œ ์‚ฌ์šฉํ•œ๋‹ค.

  

2. Comparable ์‚ฌ์šฉ๋ฒ• ๐ŸŒญ

  Comparable์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์•„๋ž˜์˜ Comparable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค.

public interface Comparable {
  public int comparetTo(T o);
}

  compareTo()์˜ ๋ฐ˜ํ™˜๊ฐ’์ด int๋ผ๊ณ  ํ‘œ์‹œ๋˜์–ด ์žˆ์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” 0, ์Œ์ˆ˜, ์–‘์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ๊ตฌํ˜„ํ•˜๋ฉด ๋œ๋‹ค.

  • ์Œ์ˆ˜ = ๋น„๊ตํ•˜๋Š” ๊ฐ’๋ณด๋‹ค ์ž‘์€ ๊ฒฝ์šฐ
  • 0 = ๋‘ ๊ฐ์ฒด๊ฐ€ ๊ฐ™์€ ๊ฒฝ์šฐ
  • ์–‘์ˆ˜ = ๋น„๊ตํ•˜๋Š” ๊ฐ’๋ณด๋‹ค ํฐ ๊ฒฝ์šฐ

  ๋ฐฉ๋ฌธ๊ฐ(Visitor)๋“ค์„ ๋‚˜์ด๋ณ„๋กœ ์ •๋ ฌ์„ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ด ๋ณด์ž. ๊ทธ๋Ÿฌ๋ฉด Visitor ํด๋ž˜์Šค์—์„œ compareTo๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•˜์—ฌ Comparable์„ ๊ตฌํ˜„ํ•ด ์ฃผ๋ฉด ๋œ๋‹ค.

public class Visitor implements Comparable {
	int age;
	
	public Visitor(int age) {
		this.age = age;
	}
	
	@Override
	public int compareTo(Object o) {
		return this.age - ((Visitor)o).age;
	}

	@Override
	public String toString() {
		return "Visitor [age=" + age + "]";
	}
}
public class Main {
	public static void main(String[] args) {
		List<Visitor> visitors = Arrays.asList(new Visitor(40), new Visitor(20), new Visitor(32));
        
		System.out.println("์ •๋ ฌ ์ „ : " + visitors.toString());
        
		Collections.sort(visitors);
		System.out.println("์ •๋ ฌ ํ›„ : " + visitors.toString());
	}
}
// ์ •๋ ฌ ์ „ : [Visitor [age=40], Visitor [age=20], Visitor [age=32]]
// ์ •๋ ฌ ํ›„ : [Visitor [age=20], Visitor [age=32], Visitor [age=40]]

  ๋งŒ์•ฝ์— ์ด๋ฆ„์ˆœ์œผ๋กœ ์ •๋ ฌ์„ ํ•œ๋‹ค๊ณ  ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

public class Visitor implements Comparable {
	int age;
	String name;
	
	public Visitor(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	@Override
	public int compareTo(Object o) {
		return this.name.compareTo(((Visitor)o).name);
	}

	@Override
	public String toString() {
		return "Visitor [age=" + age + ", name=" + name + "]";
	}
}

  name์˜ ํƒ€์ž…์ด String์ด๊ณ , String์—์„œ๋„ Comparable์„ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์œ„์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

3. Comparator ์‚ฌ์šฉ๋ฒ• ๐ŸŒฎ

Collections.sort(visitors); // 1
Collecitons.sort(visitors, nameLengthComparator()); // 2

  Comparable์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” 2๋ฒˆ์ฒ˜๋Ÿผ Comparator๋ฅผ ์ง€์ •ํ•ด์ฃผ์ง€ ์•Š๊ณ  1๋ฒˆ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•˜์˜€๋‹ค. ๋งŒ์•ฝ Comparator๋ฅผ ์ง€์ •ํ•ด์ฃผ์ง€ ์•Š์œผ๋ฉด ์ •๋ ฌํ•˜๋Š” ๊ฐ์ฒด์—์„œ Comparable์„ ๊ตฌํ˜„ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์ •๋ ฌ์ด ๋œ๋‹ค. ํ•˜์ง€๋งŒ Comparator์„ ์ง€์ •ํ•ด ์ฃผ๋ฉด ์ง€์ •๋œ ๋ฐฉ์‹์œผ๋กœ ์ •๋ ฌ์ด ๋œ๋‹ค.

public interface Comparator {
  int compare(T o1, T o2);
}

  Comparator์˜ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์œ„์™€ ๊ฐ™๊ณ  Comparable์—์„œ compareTo()๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•œ ๊ฒƒ์ฒ˜๋Ÿผ compare()๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉ ํ•˜๋ฉด ๋œ๋‹ค.

  • ์Œ์ˆ˜ = ๋น„๊ตํ•˜๋Š” ๊ฐ’๋ณด๋‹ค ์ž‘์€ ๊ฒฝ์šฐ
  • 0 = ๋‘ ๊ฐ์ฒด๊ฐ€ ๊ฐ™์€ ๊ฒฝ์šฐ
  • ์–‘์ˆ˜ = ๋น„๊ตํ•˜๋Š” ๊ฐ’๋ณด๋‹ค ํฐ ๊ฒฝ์šฐ

  ์ด๋ฒˆ์—๋Š” ๋ฐฉ๋ฌธ๊ฐ๋“ค์„ ์ด๋ฆ„์˜ ๊ธธ์ด๋กœ ์ •๋ ฌํ•ด ๋ณด์ž. Comparator๋ฅผ ๊ตฌํ˜„ํ•  NameLengthComparator ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๊ณ , gํ•ด๋‹น ํด๋ž˜์Šค์—์„œ compare๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•˜์—ฌ ๊ตฌํ˜„ํ•˜๋ฉด ๋œ๋‹ค.

public class NameLengthComparator implements Comparator<String> {
	@Override
	public int compare(String o1, String o2) {
		return o1.length() - o2.length();
	}
}
public class Main {
	public static void main(String[] args) {
		List<String> visitors = Arrays.asList("emma", "tom", "andrea");
        
		System.out.println("์ •๋ ฌ ์ „ : " + visitors.toString());
		Collections.sort(visitors);
        
		System.out.println("Comparable์„ ํ™œ์šฉํ•œ ์ •๋ ฌ ํ›„ : " + visitors.toString());
        
		Collections.sort(visitors, new NameLengthComparator());
		System.out.println("Comparator์„ ํ™œ์šฉํ•œ ์ •๋ ฌ ํ›„ : " + visitors.toString());
	}
}

// ์ •๋ ฌ ์ „ : [emma, tom, andrea]
// Comparable์„ ํ™œ์šฉํ•œ ์ •๋ ฌ ํ›„ : [andrea, emma, tom]
// Comparator์„ ํ™œ์šฉํ•œ ์ •๋ ฌ ํ›„ : [tom, emma, andrea]

 

4. ์ต๋ช… ํด๋ž˜์Šค๋ฅผ ํ™œ์šฉํ•œ Comparator ๊ตฌํ˜„ ๐Ÿฅช

  ๋ฐฉ๋ฌธ๊ฐ๋“ค์„ ์ด๋ฆ„์˜ ๊ธธ์ด๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋‚˜์ด, ์„ฑ๋ณ„, ๊ตญ๊ฐ€, ๋„์ฐฉํ•œ ์‹œ๊ฐ„ ๋“ฑ์œผ๋กœ ์ •๋ ฌ์„ ํ•˜๋ ค๋ฉด ๊ณ„์†ํ•ด์„œ XXXcomparator ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ• ๊นŒ? ๋ฌผ๋ก  ๊ทธ๋Ÿด ์ˆ˜๋„ ์žˆ์ง€๋งŒ ์ •๋ ฌ์„ ํ•  ๋•Œ ํ•œ๋ฒˆ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋ฏ€๋กœ ํšจ์œจ์ ์ด์ง€ ๋ชปํ•˜๋‹ค. ๋งŒ์•ฝ ์ต๋ช… ํด๋ž˜์Šค๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ํ•ด๋‹น ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

  ์ต๋ช… ํด๋ž˜์Šค๋Š” ๋‚ด๋ถ€ ํด๋ž˜์Šค(Inner class)(ํด๋ž˜์Šค ๋‚ด์— ์„ ์–ธ๋œ ํด๋ž˜์Šค)์˜ ์ผ์ข…์œผ๋กœ ์ด๋ฆ„์ด ์—†๋Š” ํด๋ž˜์Šค๋‹ค. ์ด๋ฆ„์ด ์—†๋‹ค๋Š” ๊ฒƒ์€ ๋ณ„๋กœ ๊ธฐ์–ต๋˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค๋Š” ๊ฒƒ์ด๋ฉฐ, ๋‚˜์ค‘์— ๋‹ค์‹œ ๋ถˆ๋Ÿฌ์งˆ ์ด์œ ๊ฐ€ ์—†๋‹ค๋Š” ๋œป์ด๋‹ค. ๊ทธ๋ž˜์„œ ์ผ์‹œ์ ์œผ๋กœ ํ•œ ๋ฒˆ๋งŒ ์‚ฌ์šฉ๋˜๋Š” ๊ฐ์ฒด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋˜๊ฒ ๋‹ค.

  ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์€ ์•„๋ž˜์™€ ๊ฐ™์ด ๋ถ€๋ชจํด๋ž˜์Šค์ธ Comparator์˜ compare()๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•ด์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

public class Main {
	public static void main(String[] args) {
		List<String> visitors = Arrays.asList("emma", "tom", "andrea");
		System.out.println("์ •๋ ฌ ์ „ : " + visitors.toString());
		
		Collections.sort(visitors, new Comparator<String>() {
			@Override
			public int compare(String o1, String o2) {
				return o1.length() - o2.length();
			}
		});
        
		System.out.println("Comparator์„ ํ™œ์šฉํ•œ ์ •๋ ฌ ํ›„ (์ต๋ช… ํด๋ž˜์Šค ์‚ฌ์šฉO) : " + visitors.toString());
	}
}
// ์ •๋ ฌ ์ „ : [emma, tom, andrea]
// Comparator์„ ํ™œ์šฉํ•œ ์ •๋ ฌ ํ›„ (์ต๋ช… ํด๋ž˜์Šค ์‚ฌ์šฉO) : [tom, emma, andrea]

  ์ด์ƒ์œผ๋กœ Comparable๊ณผ Comparator์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์•˜๋‹ค. ์ต๋ช… ํด๋ž˜์Šค๋กœ Comparator๋ฅผ ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์•˜๋Š”๋ฐ, ๋žŒ๋‹ค(Lambda)๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. ๋‹ค์Œ ๊ธ€์—์„œ ๋žŒ๋‹ค์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๊ณ  ์–ด๋–ป๊ฒŒ ๋” ๊ฐ„๋‹จํ•ด ์ž‘์„ฑํ•˜๋Š”์ง€ ์•Œ์•„๋ณด๋„๋ก ํ•˜์ž. 

 

ํ•ด๋‹น ๊ธ€์€ ๋‚จ๊ถ ์„ฑ๋‹˜์˜ Java์˜ ์ •์„์„ ์ฝ๊ณ  ์ž‘์„ฑํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๋Œ“๊ธ€์ˆ˜0