在Java集合框架中有两种比较接口: Comparable 接口和 Comparator 接口。
一、Comparable 接口
public interface Comparable<T> { public int compareTo(T o); }
一个类实现了 Camparable 接口表明这个类的对象之间是可以相互比较的。如果数组或者集合中的(类)元素实现了该接口的话 , 我们就可以调用 Collections.sort 和 Arrays.sort 排序,或应用于有序集合 TreeSet 和 TreeMap 中。
public class Test { public static void main(String[] args) { Person[] persons = { new Person(10, "P1"), new Person(35, "P2"), new Person(60, "P3"), new Person(10, "P4"), new Person(40, "P5"), new Person(10, "P6") }; Person[] persons2 = persons; Person[] persons3 = persons; System.out.println("Before Sort:" + Arrays.toString(persons)); Arrays.sort(persons); System.out.println("Arrays.sort:" + Arrays.toString(persons)); Collections.sort(Arrays.asList(persons2)); System.out.println("Collections.sort:" + Arrays.toString(persons2)); TreeSet<Person> set = new TreeSet<Person>(); TreeMap<Person, String> map = new TreeMap<Person, String>(); for(int i = 0; i < persons3.length; i++) { set.add(persons3[i]); map.put(persons3[i], "P" + (i + 1)); } System.out.println("TreeSet:" + Arrays.toString(persons2)); System.out.println("TreeMap:" + Arrays.toString(persons2)); } } class Person implements Comparable<Person>{ private int age; private String name; public Person(int age, String name) { this.age = age; this.name = name; } public int compareTo(Person person) { int cop = age - person.getAge(); return cop != 0 ? cop : name.compareTo(person.getName()); } // 一般来说,一个类如果涉及到比较,应该重写equals()方法,因为内存地址比较没有意义。 public boolean equals(Object o) { if(!(o instanceof Person)) return false; Person person = (Person) o; return (age == person.getAge()) && (name.equals(person.getName())); } // 覆盖 equals() 和 hashCode() 以确保两个相等的对象返回同一个哈希码。 public int hashcode() { int result = 17; result = 37 * result + age; result = 37 * result + name.hashCode(); return result; } public String toString() { return age + "-" + name; } public int getAge() { return age; } public String getName() { return name; } }
运行结果
Before Sort:[10-P1, 35-P2, 60-P3, 10-P4, 40-P5, 10-P6]
Arrays.sort:[10-P1, 10-P4, 10-P6, 35-P2, 40-P5, 60-P3]
Collections.sort:[10-P1, 10-P4, 10-P6, 35-P2, 40-P5, 60-P3]
TreeSet:[10-P1, 10-P4, 10-P6, 35-P2, 40-P5, 60-P3]
TreeMap:[10-P1, 10-P4, 10-P6, 35-P2, 40-P5, 60-P3]
二、 Comparator 接口
public interface Comparator<T> { int compare(T o1, T o2); }
Comparator 可以看成一种算法的实现,在需要容器集合实现比较功能的时候,来指定这个比较器,这可以看成一种设计模式,将算法和数据分离。Comparator的应用场景:
1 、如果类的设计师没有考虑到 Compare 的问题而没有实现 Comparable 接口,可以通过 Comparator 来实现比较算法进行排序;
2 、为了使用不同的排序标准做准备,比如:升序、降序或其他什么序。
public class Test { public static void main(String[] args) { Person[] persons = { new Person(10, "P1"), new Person(35, "P2"), new Person(60, "P3"), new Person(10, "P4"), new Person(40, "P5"), new Person(10, "P6") }; Person[] persons2 = persons; System.out.println("Before Sort:" + Arrays.toString(persons)); Arrays.sort(persons, new PersonComparator()); System.out.println("Arrays.sort:" + Arrays.toString(persons)); Collections.sort(Arrays.asList(persons2), new PersonComparator()); System.out.println("Collections.sort:" + Arrays.toString(persons2)); } } class PersonComparator implements Comparator<Person> { @Override public int compare(Person p1, Person p2) { int cop = p1.getAge() - p2.getAge(); return cop != 0 ? cop : p1.getName().compareTo(p2.getName()); } }
运行结果
Before Sort:[10-P1, 35-P2, 60-P3, 10-P4, 40-P5, 10-P6]
Arrays.sort:[10-P1, 10-P4, 10-P6, 35-P2, 40-P5, 60-P3]
Collections.sort:[10-P1, 10-P4, 10-P6, 35-P2, 40-P5, 60-P3]