Java集合(一)--Comparable和Comparator

Comparable:

  是集合内部的方法实现的排序,只有一个方法

public interface Comparable<T> {
    public int compareTo(T o);
}

对于String和一些基本数据类型,默认实现了Comparable 接口,实现了compareTo方法,可以直接使用。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }
} 

public final class Integer extends Number implements Comparable<Integer> { 
    public int compareTo(Integer anotherInteger) {
        return compare(this.value, anotherInteger.value);
    }
} 

使用场景:

  同一个类的两个对象相互比较,类内部的比较

  可以进行排序,但是一定要实现Comparable,否则出现异常

  Collections.sort()和Arrays.sort()内部都有应用

使用样例:

@Slf4j
@Data
@AllArgsConstructor
public class TestUnit implements Comparable<TestUnit>{

    private String name;
    private Integer age;

    @Override
    public int compareTo(TestUnit o) {
        return this.age.compareTo(o.age);
    }

    public static void main(String[] args) {
        List<TestUnit> list = new ArrayList<TestUnit>();
        list.add(new TestUnit("a",2));
        list.add(new TestUnit("b",1));
        list.add(new TestUnit("c",3));
        System.out.println(list);
        Collections.sort(list);
        System.out.println(list);

     TestUnit unit = new TestUnit("a", 1);
     TestUnit unit1 = new TestUnit("b", 2);
     System.out.println(unit.compareTo(unit1));
} }

结果:

[TestUnit(name=a, age=2), TestUnit(name=b, age=1), TestUnit(name=c, age=3)]
[TestUnit(name=b, age=1), TestUnit(name=a, age=2), TestUnit(name=c, age=3)]
-1

Comparator:

  是集合外部的方法实现的排序,多个方法

public interface Comparator<T> {
    int compare(T o1, T o2);
    
    public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));
    }
}

使用场景:

  Comparator接口代码更加灵活,可以定义某个类的多个比较器,以满足不用的需求,而不改变对象自身,而用一个策略对象来改变对象的比较

行为(策略模式)。

使用样例:

@Slf4j
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TestUnit implements Comparator<TestUnit> {

    private String name;
    private Integer age;


    public static void main(String[] args) {
        List<TestUnit> list = new ArrayList<TestUnit>();
        list.add(new TestUnit("a",2));
        list.add(new TestUnit("b",1));
        list.add(new TestUnit("c",3));
        System.out.println(list);
        Collections.sort(list, new TestUnit());
        System.out.println(list);

        TestUnit unit = new TestUnit("a", 1);
        TestUnit unit1 = new TestUnit("b", 2);
        System.out.println(unit.compare(unit, unit1));;
    }

    @Override
    public int compare(TestUnit o1, TestUnit o2) {
        return o1.age - o2.age;
    }
}

结果:

[TestUnit(name=a, age=2), TestUnit(name=b, age=1), TestUnit(name=c, age=3)]
[TestUnit(name=b, age=1), TestUnit(name=a, age=2), TestUnit(name=c, age=3)]
-1

注意事项:

  无论是Comparable还是Comparator实现类在重写compareTo、compare方法时,一般要求compare(o1,o2))==0的逻辑结果要和o1.equals(o2)

保持一致。

总结:

(1)如果比较的方法只用在一个类中,则该类实现Comparable接口就可以

(2)如果比较的方法在很多类中需要用到,就自己写个类实现Comparator接口,实现松耦合

(3)在用Collections类的sort方法排序时,若不指定Comparator,那就以自然顺序排序(自然顺序就是实现Comparable接口设定的排序方式)

参考:https://mp.weixin.qq.com/s/GBJf5eHxhoUwlpm0BB1jpA

原文地址:https://www.cnblogs.com/huigelaile/p/10855684.html