当前位置:   article > 正文

java中比较器Comparator的使用(结合PriorityQueue)_priorityqueue的comparator接口

priorityqueue的comparator接口

上期我们简单的介绍了下java中的排序接口Comparable的使用,由于Comparable是不够灵活的一种排序接口,它要去修改对象的类的代码。所以,我们今天介绍一款较为灵活的比较器接口Comparator。

首先,还是创建一个实体类Person2:

  1. public class Person2 {
  2. private int age;
  3. private String name;
  4. private int xuehao;
  5. public Person2() {
  6. }
  7. public Person2(int age, String name, int xuehao) {
  8. this.age = age;
  9. this.name = name;
  10. this.xuehao = xuehao;
  11. }
  12. public int getXuehao() {
  13. return xuehao;
  14. }
  15. public void setXuehao(int xuehao) {
  16. this.xuehao = xuehao;
  17. }
  18. public int getAge() {
  19. return age;
  20. }
  21. public void setAge(int age) {
  22. this.age = age;
  23. }
  24. public String getName() {
  25. return name;
  26. }
  27. public void setName(String name) {
  28. this.name = name;
  29. }
  30. @Override
  31. public String toString() {
  32. return "Person2{" +
  33. "age=" + age +
  34. ", name='" + name + '\'' +
  35. ", xuehao=" + xuehao +
  36. '}';
  37. }
  38. }

然后在我们的创作一个测试类Mytest:

  1. public class Mytest {
  2. public static void main(String[] args) {
  3. Person2[] person2s = {new Person2(15,"张三",34),
  4. new Person2(5, "李四",12),
  5. new Person2(10, "王五",88)};
  6. //创建比较器对象cp
  7. Comparator<Person2> cp = new Comparator<Person2>() {
  8. @Override//重写compare方法,使按照xuehao升序
  9. //o2.getXuehao()-o1.getXuehao():按照xuehao降序
  10. public int compare(Person2 o1, Person2 o2) {
  11. return o1.getXuehao()-o2.getXuehao();
  12. }
  13. };
  14. System.out.println("排序前:");
  15. for(Person2 p:person2s){
  16. System.out.println(p.toString());
  17. }
  18. //对数组person2s安装比较器cp进行排序
  19. Arrays.sort(person2s, cp);
  20. System.out.println("排序后:");
  21. for(Person2 p:person2s){
  22. System.out.println(p.toString());
  23. }
  24. }
  25. }

运行结果如下:(按照xuehao升序)

  1. 排序前:
  2. Person2{age=15, name='张三', xuehao=34}
  3. Person2{age=5, name='李四', xuehao=12}
  4. Person2{age=10, name='王五', xuehao=88}
  5. 排序后:
  6. Person2{age=5, name='李四', xuehao=12}
  7. Person2{age=15, name='张三', xuehao=34}
  8. Person2{age=10, name='王五', xuehao=88}

当然,你也可以修改比较器中的compare方法,使其安装age降序,具体修改如下:

  1. //创建比较器对象cp
  2. Comparator<Person2> cp = new Comparator<Person2>() {
  3. @Override//重写compare方法,使按照age降序
  4. public int compare(Person2 o1, Person2 o2) {
  5. //若为o1.getAge()-o2.getAge():按照age升序
  6. return o2.getAge()-o1.getAge();
  7. }
  8. };

修改后,运行结果如下:

  1. 排序前:
  2. Person2{age=15, name='张三', xuehao=34}
  3. Person2{age=5, name='李四', xuehao=12}
  4. Person2{age=10, name='王五', xuehao=88}
  5. 排序后:
  6. Person2{age=15, name='张三', xuehao=34}
  7. Person2{age=10, name='王五', xuehao=88}
  8. Person2{age=5, name='李四', xuehao=12}

可以发现我们修改person2的排序方式并不用去修改person2中的代码,所以说Comparator比Comparable更加的灵活。

最后我们看下Comparator在优先队列中的使用,我们修改Mytest中的代码如下:

  1. public class Mytest {
  2. public static void main(String[] args) {
  3. //创建一个比较器
  4. Comparator<Person2> cp = new Comparator<Person2>() {
  5. @Override
  6. public int compare(Person2 o1, Person2 o2) {
  7. //安照年龄升序
  8. return o1.getAge()-o2.getAge();
  9. }
  10. };
  11. //将比较器cp作为参数创建一个优先队列
  12. PriorityQueue<Person2> priorityQueue = new PriorityQueue<>(cp);
  13. //往队列中加入数据
  14. priorityQueue.add(new Person2(15,"张三",2));
  15. priorityQueue.add(new Person2(33,"张三",78));
  16. priorityQueue.add(new Person2(1,"张三",33));
  17. priorityQueue.add(new Person2(5, "李四",14));
  18. priorityQueue.add(new Person2(55,"张三",35));
  19. priorityQueue.add(new Person2(10, "王五",22));
  20. System.out.println("遍历优先队列:");
  21. for(Person2 p:priorityQueue){
  22. System.out.println(p.toString());
  23. }
  24. System.out.println("依次弹出优先队列中的值");
  25. while(!priorityQueue.isEmpty()){
  26. System.out.println(priorityQueue.poll());
  27. }
  28. }
  29. }

运行结果如下:

  1. 遍历优先队列:
  2. Person2{age=1, name='张三', xuehao=33}
  3. Person2{age=5, name='李四', xuehao=14}
  4. Person2{age=10, name='王五', xuehao=22}
  5. Person2{age=33, name='张三', xuehao=78}
  6. Person2{age=55, name='张三', xuehao=35}
  7. Person2{age=15, name='张三', xuehao=2}
  8. 依次弹出优先队列中的值
  9. Person2{age=1, name='张三', xuehao=33}
  10. Person2{age=5, name='李四', xuehao=14}
  11. Person2{age=10, name='王五', xuehao=22}
  12. Person2{age=15, name='张三', xuehao=2}
  13. Person2{age=33, name='张三', xuehao=78}
  14. Person2{age=55, name='张三', xuehao=35}

显然,重结果中我们可以看出,优先队列弹出元素的顺序是按照age升序的。同时,细心的同学可以从我们的遍历结果中发现,优先队列中各个元素是按照其年龄(age)值来维护了一个完全二叉树的小顶堆,如下图所示:(节点中为各个元素age的值)

 

下面我们去修改比较器,具体代码如下:

  1. //创建一个比较器
  2. Comparator<Person2> cp = new Comparator<Person2>() {
  3. @Override
  4. public int compare(Person2 o1, Person2 o2) {
  5. //按照xuehao降序
  6. return o2.getXuehao()-o1.getXuehao();
  7. }
  8. };

 然后再运行,得到如下结果:

  1. 遍历优先队列:
  2. Person2{age=33, name='张三', xuehao=78}
  3. Person2{age=55, name='张三', xuehao=35}
  4. Person2{age=1, name='张三', xuehao=33}
  5. Person2{age=15, name='张三', xuehao=2}
  6. Person2{age=5, name='李四', xuehao=14}
  7. Person2{age=10, name='王五', xuehao=22}
  8. 依次弹出优先队列中的值
  9. Person2{age=33, name='张三', xuehao=78}
  10. Person2{age=55, name='张三', xuehao=35}
  11. Person2{age=1, name='张三', xuehao=33}
  12. Person2{age=10, name='王五', xuehao=22}
  13. Person2{age=5, name='李四', xuehao=14}
  14. Person2{age=15, name='张三', xuehao=2}

此时我们可以发现我们元素的弹出顺序是按照xuehao降序的,而遍历的结果是按照xuehao来维护的一个大顶堆(如下图 )。

至此,我们可以总结为如下:

在优先队列中,如果定义的比较器是按照某值X升序(return o1.X-o2.X)排序的,那么优先队列中元素的位置会按照X的值所构建的小顶堆来放置;

在优先队列中,如果定义的比较器是按照某值X降序(return o2.X-o1.X)排序的,那么优先队列中元素的位置会按照X的值所构建的大顶堆来放置;

在使用比较器的时候,你也可以先创建一个比较器的类,然后在要使用的时候去new一个该类的对象也可以。比如在我们例子中,我们可以去创建下面这个类:

  1. public class MyComparator implements Comparator<Person2> {
  2. @Override
  3. public int compare(Person2 o1, Person2 o2) {
  4. //按照年龄age升序
  5. return o1.getAge()-o2.getAge();
  6. }
  7. }

然后在使用的时候直接去创建该类的对象,可以将我们的测试类的代码修改如下部分:

  1. //创建一个比较器
  2. // Comparator<Person2> cp = new Comparator<Person2>() {
  3. // @Override
  4. // public int compare(Person2 o1, Person2 o2) {
  5. // //按照xuehao降序
  6. // return o2.getXuehao()-o1.getXuehao();
  7. // }
  8. // };
  9. //此处比较器的排序规则要到MyComparator中去查看或修改
  10. MyComparator cp = new MyComparator();

比较器接口Comparator的介绍到此就暂告一段落了,若文中有描述不当之处,希望大家多多指出,我们一起学习一起进步。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/355111?site
推荐阅读
相关标签
  

闽ICP备14008679号