常见的接口与类 -- Comparator

Comparable和Comparator

Java提供了一个用于比较的接口Comparable,实际上Java中还提供了一个接口Comparator,该接口也具有比较的功能,其更注重的是比较容器,然后对其排序。

  • Comparable在java.lang包中,它是排序接口,若一个类实现了Comparable接口,就意味着“该类支持排序”,其相当于“内部比较器”。
  • Comparator在java.util包中,它是比较器,我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序,其相当于“外部比较器”。

两种方法各有优劣, 用Comparable 简单, 只要实现Comparable 接口的对象直接就成为一个可以比较的对象,但是需要修改源代码。 用Comparator 的好处是不需要修改源代码, 而是另外实现一个比较器, 当某个自定义的对象需要作比较的时候,把比较器和对象一起传递过去就可以比大小了, 并且在Comparator 里面用户可以自己实现复杂的可以通用的逻辑,使其可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。

使用场景

  • 排序
    需要比较两个对象谁排在前谁排在后
  • 分组
    需要比较两个对象是否是属于同一组

接口方法

作为接口Comparator提供了两个抽象方法:

返回值 方法
int compare(T o1, T o2) 比较用来排序的两个参数
boolean equals(Object obj) 指示某个其他对象是否“等于”此 Comparator

Compare() 比较用来排序的两个参数。根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数(>0是代表自然正序排列,<0代表自然排序倒序)。

  • return 1 时,按照从小到大排序
  • return 0 时,原位置不动
  • return -1 时,按照从大到小排序

类实现Comparator接口时,只需要实现compare方法,因为Java中类都继承于Object类,而Object类默认实现了equals方法,所以不需要必须去实现equals方法。

实践操作

排序时,两个对象比较的结果有三种:大于,等于,小于。
分组时,两个对象比较的结果只有两种:等于(两个对象属于同一组),不等于(两个对象属于不同组)。

排序

降序排列:

public class Main {
    public static void main(String[] args) {
        // write your code here
        //要想改变默认的排列顺序,不能使用基本类型(int,double, char),而要使用它们对应的类
        Integer[] nums = {2,4345,224,563,24,45};
        Arrays.sort(nums,new MyComparator());
        System.out.println(Arrays.toString(nums));
    }
}
class MyComparator implements Comparator<Integer> {
    //如果o1小于o2,我们就返回正值(自然排序),如果o1大于o2我们就返回负值(自然倒序)
    @Override
    public int compare(Integer o1, Integer o2) {
        return o2-o1; //降序
    }
}

结果:

[4345, 563, 224, 45, 24, 2]

二维数组排序:

    public static void main(String[] args){
        int[][] points = {{7,16},{2,8},{3,6},{10,12}};
        Arrays.sort(points, new Comparator<int[]>() {
            public int compare(int[] point1, int[] point2) {
                return point1[1] - point2[1]; //右边界升序
            }
        });
        for(int[] arr:points){
            System.out.println(Arrays.toString(arr));
        }
    }

结果:

[3, 6]
[2, 8]
[10, 12]
[7, 16]

分组

public class GroupTest {
    class Apple {
    public String color;
    public int weight;

    public Apple(String color, int weight) {
        super();
        this.color = color;
        this.weight = weight;
    }

    @Override
    public String toString() {
        return "Apple [color=" + color + ", weight=" + weight + "]";
    }
    }

    public static <T> List<List<T>> divider(Collection<T> datas, Comparator<? super T> c) {
        List<List<T>> result = new ArrayList<List<T>>();
        for (T t : datas) {
            boolean isSameGroup = false;
            for (int j = 0; j < result.size(); j++) {
                if (c.compare(t, result.get(j).get(0)) == 0) {
                    isSameGroup = true;
                    result.get(j).add(t);
                    break;
                }
            }
            if (!isSameGroup) {
                // 创建
                List<T> innerList = new ArrayList<T>();
                result.add(innerList);
                innerList.add(t);
            }
        }
        return result;
    }

    public static void main(String[] args) {
    List<Apple> list = new ArrayList<>();
    list.add(new GroupTest().new Apple("红", 205));
    list.add(new GroupTest().new Apple("红", 131));
    list.add(new GroupTest().new Apple("绿", 248));
    list.add(new GroupTest().new Apple("绿", 153));
    list.add(new GroupTest().new Apple("黄", 119));
    list.add(new GroupTest().new Apple("黄", 224));
    List<List<Apple>> byColors = divider(list, new Comparator<Apple>() {

        @Override
        public int compare(Apple o1, Apple o2) {
        // 按颜色分组
        return o1.color.compareTo(o2.color);
        }
    });
    System.out.println("按颜色分组" + byColors);
    List<List<Apple>> byWeight = divider(list, new Comparator<Apple>() {

        @Override
        public int compare(Apple o1, Apple o2) {
        // 按重量级

        return (o1.weight / 100 == o2.weight / 100) ? 0 : 1;
        }
    });
    System.out.println("按重量级分组" + byWeight);
    }
}

结果:

// 按颜色分组
[
[Apple [color=红, weight=205],Apple [color=红, weight=131]],
[Apple [color=绿, weight=248],Apple [color=绿, weight=153]],
[Apple [color=黄, weight=119],Apple [color=黄, weight=224]]
]

//按重量级分组
[
[Apple [color=红, weight=205],Apple [color=绿, weight=248],Apple [color=黄, weight=224]],
[Apple [color=红, weight=131],Apple [color=绿, weight=153],Apple [color=黄, weight=119]]
]
posted @ 2021-06-06 16:47  当康  阅读(355)  评论(0编辑  收藏  举报