1. 基本类型比较
package compare;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 基础类型比较
*/
public class CollectionsTest1 {
public static void main(String[] args) {
List<String> strList = new ArrayList<>();
strList.add("15");
strList.add("12");
strList.add("18");
// 字符串排序
Collections.sort(strList);
System.out.println("*******字符串排序********");
strList.forEach(System.out::println);
System.out.println("*************集合元素“逆向输出(反转)”而非“逆向排序”***********");
Collections.reverse(strList);
strList.forEach(System.out::println);
List<Integer> intList = new ArrayList<>();
intList.add(15);
intList.add(12);
intList.add(18);
// 整型排序
Collections.sort(intList);// 升序排列
System.out.println("*************整数类型排序***********");
intList.forEach(System.out::println);
System.out.println("*************集合元素“逆向输出(反转)”而非“逆向排序”***********");
Collections.reverse(intList);
intList.forEach(System.out::println);
/**
* 为什么基础类型的集合,可以直接调用sort排序,而不需要重新 实现 Comparable 接口类?
* 查看底层源码可知:
* Sorts the specified list into ascending order, according to the natural ordering of its elements.
* All elements in the list must implement the Comparable interface. Furthermore, all elements in the
* list must be mutually comparable (that is, e1.compareTo(e2) must not throw a ClassCastException for
* any elements e1 and e2 in the list).
* 调用该sort()方法的前提条件时,该集合list的类型T必须实现Comparable才行,
* 但是基础类型默认都实现了Comparable接口,所以可以直接使用sort方法:
* 1.public final class Integer extends Number implements Comparable<Integer>
* 2.public final class Double extends Number implements Comparable<Double>
* 3.public final class Long extends Number implements Comparable<Long>
* ......
* 而String也实现了Comparable接口:
* public final class String implements java.io.Serializable, Comparable<String>, CharSequence
* 所以都可以直接调用sort方法。
*
* 而对于对象而言,其不是基础类型,需要使用Collections.sort()方法时对象需要实现Comparable接口,然后重写compareTo()方法,在方法体中自定义比较规则。
*
* 参考链接:
* https://www.cnblogs.com/darkings/p/16414530.html
* https://blog.youkuaiyun.com/u012062455/article/details/78087314
*
* 补充:
* reverse的意思是反转,而不是降序,只是将原来集合的元素顺序反转一下输出,反转并不意味着降序了,要真正的实现降序,可以先对集合进行升序,然后进行反转,就可以实现降序了。
*/
}
}
输出结果:
*******字符串排序******** 12 15 18 *************集合元素“逆向输出(反转)”而非“逆向排序”*********** 18 15 12 *************整数类型排序*********** 12 15 18 *************集合元素“逆向输出(反转)”而非“逆向排序”*********** 18 15 12
2. 对象类型比较
2.1 list.stream().sorted()
参考链接:JAVA集合多字段排序方法 - 未月廿三 - 博客园
List<类> list; 代表某集合 //返回 对象集合以类属性一升序排序 list.stream().sorted(Comparator.comparing(类::属性一)); //返回 对象集合以类属性一降序排序 注意两种写法 list.stream().sorted(Comparator.comparing(类::属性一).reversed());//先以属性一升序,对升序结果进行属性一降序 list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()));//以属性一降序 //返回 对象集合以类属性一升序 属性二升序 list.stream().sorted(Comparator.comparing(类::属性一).thenComparing(类::属性二)); //返回 对象集合以类属性一降序 属性二升序 注意两种写法 list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二));//先以属性一升序,对升序结果进行属性一降序,再进行属性二升序 list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()).thenComparing(类::属性二));//先以属性一降序,再进行属性二升序 //返回 对象集合以类属性一降序 属性二降序 注意两种写法 list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二,Comparator.reverseOrder()));//先以属性一升序,对升序结果进行属性一降序,再进行属性二降序 list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()).thenComparing(类::属性二,Comparator.reverseOrder()));//先以属性一降序,再进行属性二降序 //返回 对象集合以类属性一升序 属性二降序 注意两种写法 list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二).reversed());//先以属性一升序,对升序结果进行属性一降序,再进行属性二升序,对前面结果进行属性一降序属性二降序(优先按照属性一降序,属性一相等时再按照属性二降序) list.stream().sorted(Comparator.comparing(类::属性一).thenComparing(类::属性二,Comparator.reverseOrder()));//先以属性一升序,再进行属性二降序
通过以上例子我们可以发现:
-
Comparator.comparing(类::属性一).reversed();
-
Comparator.comparing(类::属性一,Comparator.reverseOrder());
两种排序是完全不一样的,一定要区分开来:
1、是得到排序结果后再排序,
2、是直接进行排序,很多人会混淆导致理解出错,2更好理解,建议使用2
-
Img类
package compare;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import lombok.Data;
import lombok.ToString;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
@Data
@ToString
public class Img {
private Integer id;
private Integer sort;
private Date createTime;
public static void main(String[] args) {
List<Img> list = CollUtil.newArrayList();
for (int i = 1; i <= 3; i++) {
Img img = new Img();
img.setId(i);
img.setSort(i != 1 ? 2 : 1);
img.setCreateTime(i == 1 ? DateUtil.offset(new Date(), DateField.MINUTE, 3) : i == 2 ? DateUtil.offset(new Date(), DateField.MINUTE, 1) : DateUtil.offset(new Date(), DateField.MINUTE, 2));
list.add(img);
}
System.out.println("现有集合:");
list.stream().forEach(item -> System.out.println(item));
System.out.println("使用reversed()排序:");
List<Img> imgList = list.stream().sorted(Comparator.comparing(Img::getSort).thenComparing(Img::getCreateTime).reversed()).collect(Collectors.toList());
imgList.stream().forEach(item -> System.out.println(item));
System.out.println("使用Comparator.reverseOrder()排序:");
List<Img> imgs = list.stream().sorted(Comparator.comparing(Img::getSort).thenComparing(Img::getCreateTime, Comparator.reverseOrder())).collect(Collectors.toList());
imgs.stream().forEach(item -> System.out.println(item));
}
}
输出结果:
现有集合: Img(id=1, sort=1, createTime=2022-09-22 20:52:42) Img(id=2, sort=2, createTime=2022-09-22 20:50:42) Img(id=3, sort=2, createTime=2022-09-22 20:51:42) 使用reversed()排序: Img(id=3, sort=2, createTime=2022-09-22 20:51:42) Img(id=2, sort=2, createTime=2022-09-22 20:50:42) Img(id=1, sort=1, createTime=2022-09-22 20:52:42) 使用Comparator.reverseOrder()排序: Img(id=1, sort=1, createTime=2022-09-22 20:52:42) Img(id=3, sort=2, createTime=2022-09-22 20:51:42) Img(id=2, sort=2, createTime=2022-09-22 20:50:42)
2.2 Collections.sort()
@Override
public int compareTo(Object o) {
return 0;
}
方法原理:利用当前对象和传入的目标对象进行比较,通过返回值,决定顺序。
(1)当返回值是 “-1”,代表从大到小排序;
(2)当返回值是 “1”,代表从小到大排序;
(3)当返回值是 “0”,两对象相等;
-
User
package compare;
import lombok.*;
import lombok.experimental.Accessors;
@Data
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Accessors(chain = true)
public class User implements Comparable{
private String name;
private Integer age;
@Override
public int compareTo(Object o) {
// 1.单条件比较
// if(o instanceof User){
// User user = (User)o;
// return this.name.compareTo(user.getName());// 按照name升序排列
//
//// return this.age.compareTo(user.getAge());// 按照age升序排列
//// return this.age - user.getAge();// 按照age升序排列
// }
//
// 2.多条件比较
if(o instanceof User){
User user = (User)o;
if(this.age>user.getAge()){
return 1;
}else if(this.age<user.getAge()){
return -1;
}else{
return this.name.compareTo(user.getName());
}
}
throw new ClassCastException("类型转换异常");
}
}
-
测试
package compare;
import java.util.*;
/**
* 对象类型比较:根据对象的某些属性来排序
*/
public class CollectionsTest2 {
public static void main(String[] args) {
/**
* 参考链接:
* https://blog.youkuaiyun.com/qq_43842093/article/details/122934159
* https://blog.youkuaiyun.com/glenshappy/article/details/125320532
* java集合的工具类Collections中提供了两种排序的方法,分别是:
* 1.Collections.sort(List list):自然排序
* 要求参与排序的对象(包含基本属性、getter/setter方法、有参/无参构造方法、toString方法)实现Comparable接口,并重写其中的compareTo()方法,方法体中定义对象的大小比较原则
*
* 2.Collections.sort(List list,Comparator c)
* 也叫定制排序/自定义排序,需编写匿名内部类,先new一个Comparator接口的比较器对象c,同时实现compare()其方法;
* 然后将比较器对象c传给Collections.sort()方法的参数列表中,实现排序功能。
*
* 第二种方法说明第一种方法不够灵活,实体类实现了comparable接口后,会增加耦合,
* 如果在项目中不同的位置需要根据不同的属性调用排序方法时,需要反复修改比较规则(按name还是按age),二者只能选择其一,会起冲突,
* 第二种方法就很好地解决了这个问题,在需要的地方创建个内部类的实例,重写其比较方法即可。
*
*
*/
List<User> userList = new ArrayList<>();
userList.add(new User("tom",18));
userList.add(new User("jack",20));
userList.add(new User("rose",15));
userList.add(new User("jerry",17));
userList.add(new User("liming",17));
userList.add(new User("rose",19));
System.out.println("------------排序前:-----------");
userList.forEach(System.out::println);
List<User> userList1 = userList;
List<User> userList2 = userList;
List<User> userList3= userList;
List<User> userList4= userList;
List<User> userList5= userList;
// 1.测试Collections.sort(List list)按照自然规则排序:单一规则
Collections.sort(userList);// 更换name或age比较规则时需要在重写的compareTo()方法中修改方法体,只能定义单一比较规则
System.out.println("------------Collections.sort(List list)排序后:--------------");
userList.forEach(System.out::println);
System.out.println("------------使用迭代器对实现Comparable接口对象集合进行输出,效果与Collections.sort(List list)一致-------------------");
Iterator<User> iterator = userList3.iterator();
while (iterator.hasNext()){
User next = iterator.next();
System.out.println(next);
}
// 2.1 测试Collections.sort(List list,Comparator c)按age自定义排序:单一规则
// Collections.sort(userList1, new Comparator<User>() {
// @Override
// public int compare(User o1, User o2) {
// return o1.getAge() - o2.getAge();
// }
// });
// 简化
Collections.sort(userList1, (o1,o2)-> o1.getAge() - o2.getAge());// o1.getAge() - o2.getAge():升序排列,o2.getAge() - o1.getAge():降序排列
System.out.println("-------------Collections.sort(List list)按age升序排列后:-----------------");
userList1.forEach(System.out::println);
// 2.2 测试Collections.sort(List list,Comparator c)按name自定义排序:单一规则
Collections.sort(userList2, (e1,e2)->e1.getName().compareTo(e2.getName()));// e1.getName().compareTo(e2.getName()):升序排列,e1.getName().compareTo(e2.getName()):降序排列
System.out.println("-------------Collections.sort(List list)按name升序排列后:-----------------");
userList2.forEach(System.out::println);
// 2.3 测试Collections.sort(List list,Comparator c)按name自定义排序:多规则
Collections.sort(userList4,((Comparator<User>)(o1, o2) -> {
return o1.getAge() - o2.getAge();// 升序
}).thenComparing((o1, o2) -> {
return o1.getName().compareTo(o2.getName());// 升序
}));
System.out.println("-------------Collections.sort(List list)先按age升序再按name升序排列后:-----------------");
userList4.forEach(System.out::println);
// 2.4 测试Collections.sort(List list,Comparator c)按name自定义排序:多规则
Collections.sort(userList5, new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
if(o1.getAge()>o2.getAge()){
return 1;
}else if(o1.getAge()<o2.getAge()){
return -1;
}else{
return o1.getName().compareTo(o2.getName());
}
}
});
System.out.println("-------------Collections.sort(List list)先按age升序再按name升序排列后:-----------------");
userList5.forEach(System.out::println);
}
}
输出结果:
------------排序前:----------- User(name=tom, age=18) User(name=jack, age=20) User(name=rose, age=15) User(name=jerry, age=17) User(name=liming, age=17) User(name=rose, age=19) ------------Collections.sort(List list)排序后:-------------- User(name=rose, age=15) User(name=jerry, age=17) User(name=liming, age=17) User(name=tom, age=18) User(name=rose, age=19) User(name=jack, age=20) ------------使用迭代器对实现Comparable接口对象集合进行输出,效果与Collections.sort(List list)一致------------------- User(name=rose, age=15) User(name=jerry, age=17) User(name=liming, age=17) User(name=tom, age=18) User(name=rose, age=19) User(name=jack, age=20) -------------Collections.sort(List list)按age升序排列后:----------------- User(name=rose, age=15) User(name=jerry, age=17) User(name=liming, age=17) User(name=tom, age=18) User(name=rose, age=19) User(name=jack, age=20) -------------Collections.sort(List list)按name升序排列后:----------------- User(name=jack, age=20) User(name=jerry, age=17) User(name=liming, age=17) User(name=rose, age=15) User(name=rose, age=19) User(name=tom, age=18) -------------Collections.sort(List list)先按age升序再按name升序排列后:----------------- User(name=rose, age=15) User(name=jerry, age=17) User(name=liming, age=17) User(name=tom, age=18) User(name=rose, age=19) User(name=jack, age=20) -------------Collections.sort(List list)先按age升序再按name升序排列后:----------------- User(name=rose, age=15) User(name=jerry, age=17) User(name=liming, age=17) User(name=tom, age=18) User(name=rose, age=19) User(name=jack, age=20)
1934

被折叠的 条评论
为什么被折叠?



