Java自定义排序返回值简单记忆理解
默认情况下:Java实现Comparator排序是升序,即自然排序
根据参数,返回值来判断是否交换
对于a,b两个参数(a在前,b在后)
jdk官方的升序基于:
< return -1
> return 1
= return 0
降序就是反过来
< return 1
> return -1
= return 0
简单记忆: 把-1理解为false,1理解为true(实际上底层源码并不是这样,实现原理参考dalao的博客,只是为了方便记忆使用)
如果要升序:那么a<b就是想要的顺序,所以return -1 ,false,不交换
如果要降序:那么a<b就是不想要的顺序,所以return 1,true,要交换
简而言之,返回1的时候进行位置交换
实践
分别对LinkedList和PriorityQueue进行测试
LInkedList
升序(默认情况)
LinkedList<Integer> list = new LinkedList<Integer>();
list.add(2);
list.add(9);
list.add(7);
list.add(5);
list.add(3);
list.add(1);
list.add(0);
Collections.sort(list, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
if(o1>o2) return 1;
else if(o1<o2) return -1;
else return 0;
}
}
);
System.out.println(list);
结果
简化代码
//可以使用LinkedList继承自List的sort方法
list.sort(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
if (o1 > o2) return 1;
else if (o1 < o2) return -1;
else return 0;
}
});
//中间的自定义比较可以用Integer中的compareTo函数代替
list.sort(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
});
使用lambda表达式进一步简化
//lambda
list.sort((a,b) ->{
if(a>b) return 1;
else if(a<b) return -1;
else return 0;
});
//lambda+compareTo()/compare()
list.sort((a,b) ->{
return a.compareTo(b);
});
list.sort((a,b)->{
return Integer.compare(a,b);
});
//lambda指向静态函数
list.sort(Integer::compareTo);
list.sort(Integer::compare);
直接调用Comparator中的naturalOrder()
list.sort(Comparator.naturalOrder());
降序
a,b交换一下顺序即可
直接使用lambda表达式+compare()/compareTo()
list.sort((a,b) ->{
return b.compareTo(a);
});
list.sort((a,b) ->{
return Integer.compare(b,a);
});
直接调用Comparator中的reverseOrder()
list.sort(Comparator.reverseOrder());
结果
PriorityQueue
优先队列默认结构为二叉小顶堆(层序遍历)
小顶堆:每个结点的值都小于或等于其左右孩子结点的值
大顶堆:每个结点的值都大于或等于其左右孩子结点的值
不清楚优先队列的同学建议先看一下这位dalao的博客
升序下的小顶堆(默认情况)
使用lambda表达式+compare()/compareTo()
PriorityQueue<Integer> queue = new PriorityQueue<>((a,b) ->{
return Integer.compare(a,b);
//return a.compareTo(b);
});
queue.offer(1);
queue.offer(9);
queue.offer(5);
queue.offer(6);
queue.offer(8);
System.out.println(queue);
结果
画图抽象出对应的二叉树结构
当然可以写成这三种形式
PriorityQueue<Integer> queue = new PriorityQueue<>(Integer::compare);
PriorityQueue<Integer> queue = new PriorityQueue<>(Integer::compareTo);
PriorityQueue<Integer> queue = new PriorityQueue<>(Comparator.naturalOrder());
降序下的大顶堆
排序规则改变之后,变成二叉大顶堆
PriorityQueue<Integer> queue = new PriorityQueue<>((a,b) ->{
return Integer.compare(b,a);
//return b.compareTo(a);
});
当然还可以写成
PriorityQueue<Integer> queue = new PriorityQueue<>(Comparator.reverseOrder());
结果
用画图抽象出对应的二叉树结构
总结
- 自定义排序规则时,需要交换则返回1,不需要交换时返回-1,相等返回0。
- 若使用lambda表达式,设定参数a,b初始顺序 与 调用函数传参顺序一致时 默认排序,即升序;位置相反时,则降序
2021/05/19
补充数组类型自定义排序
降序排序 数组
Integer[] arr = {1,2,3,4,5};
Arrays.sort(arr , (a,b) -> b-a);
当然还可以用Comparator这样写
Arrays.sort(arr, Comparator.reverseOrder());
Arrays.sort(arr, (a, b) -> b.compareTo(a));
注意:这里是必须要使用包装类型的,否则不能使用 sort 方法,因为 排序器只能对引用类型排序,而int,double等都是 primitive type (基本类型)就必须要包装成 Integer,Double 才可以