关于比较的全部

Comparator和Comparable接口

Comparable接口

Comparable is an interface for sorting. A class implement Comparable, indicates that “this class support sorting”.There is only one method in this interface: public int compareTo(T o); Suppose we use x.compareTo(y) to compare x and y: if return negative, means “x is less than y” if return 0, means “x is equal to y” if return positive, means “x is larger than y” actually “x - y”. Usually used by Collections.sort(), or Arrays.sort().

Comparator接口

Comparator is also an interface. There are two methods in this interface: int compare(T o1, T o2); // must be override boolean equals(Object obj); // not must. can inherit from Object class. For compare(x, y), return value same as compareTo(x, y). “x - y”.

Comparable是内部比较, Comparator是外部比较。

Comparable和Comparator的例子:

public class Main {
    public static void main(String[] args) {
        Person p1 = new Person("a", 5);
        Person p2 = new Person("b", 4);
        Person p3 = new Person("c", 3);
        Person p4 = new Person("c", 2);
        
        List<Person> list = new ArrayList<>(Arrays.asList(p1, p2, p3, p4));
        
        // 默认:名字从a到z,年龄从小到大(自然顺序)
        Collections.sort(list);
        for(Person p : list) {
            System.out.println(p.name + p.age); // [a5,b4,c2,c3]
        }
        
        // 年龄从小到大,再名字从a到z
        Comparator<Person> ascAgeComparator = new Comparator<Person>(){
            public int compare(Person p1, Person p2) {
                return (p1.age - p2.age == 0) ? 
                    p1.name.compareTo(p2.name) : (p1.age - p2.age);
            }
        };
        
        Collections.sort(list, ascAgeComparator);
        for(Person p : list) {
            System.out.println(p.name + p.age); // [c2,c3,b4,a5]
        }
    }
    
    private static class Person implements Comparable<Person> {
        String name;
        int age;
        public Person(String n, int a) {
            name = n;
            age = a;
        }
        
        @Override
        public int compareTo(Person person) {
            return this.name.compareTo(person.name) == 0 ? (this.age - person.age) : this.name.compareTo(person.name);
        }
    }
}

用Lambda写Comparator

public class Main {
    public static void main(String[] args) {        
        List<Integer> list = Arrays.asList(1,3,2);
        System.out.println("The original list: " + list); // [1,3,2]

        Collections.sort(list,(e1, e2)->(e1 - e2));
        System.out.println("The sorted list(e1 - e2): " + list); // [1,2,3]
        
        Collections.sort(list,(e1, e2)->(e2 - e1));
        System.out.println("The sorted list(e2 - e1): " + list); // [3,2,1]
    }
}

PriorityQueue里的Comparator

原生PriorityQueue是小顶堆。

public class Main {
    public static void main(String[] args) {
        
        PriorityQueue<Integer> pq = new PriorityQueue<>();
        pq.offer(1);
        pq.offer(5);
        pq.offer(3);
        System.out.println(pq.poll());
        System.out.println(pq.poll());
        System.out.println(pq.poll());
        System.out.println("");
        // 1,3,5
        
        pq = new PriorityQueue<>((a, b) -> (a - b));
        pq.offer(1);
        pq.offer(2);
        pq.offer(3);
        System.out.println(pq.poll());
        System.out.println(pq.poll());
        System.out.println(pq.poll());
        System.out.println("");
        // 1,2,3
        
        pq = new PriorityQueue<>((a, b) -> (b - a));
        pq.offer(1);
        pq.offer(2);
        pq.offer(3);
        System.out.println(pq.poll());
        System.out.println(pq.poll());
        System.out.println(pq.poll());
        // 3,2,1
    }
}

关于重写equals()方法:

当我们要用equals来比较自己class时,(使用hashmap也会用到),需要重写equals()方法。三步:

  1. 检查不等于null
  2. 检查instanceof
  3. 强制类型转换之后,检查properties。

重写equals()方法必须重写hashcode()方法,return一个无关紧要的,但对每个instance都不同的数即可。一般是用一个质数去乘一个property。

  • equals 是 hashcode的充分不必要条件 两个不同的object可以有一样的hashcode
  • 如果equals为true,hashcode必须返回相同的值
  • == 比较内存里的物理地址。
private class myKey {
    int i;
    int j;
    MyKey(int i, int j) {
        this.i = i;
        this.j = j;
    }
    
    @Override
    public boolean equals(Object that) {
        return that = null 
            && that instanceof MyKey 
            && ((MyKey)that).i == i 
            && ((MyKey)that).j == j;
    }
    @Override
    public int hashCode() {
        return 31 * i * j;
    }
}