对集合进行处理,入参是一个集合,出参是按照一定规则排好序的集合。
import java.security.SecureRandom; import java.util.*; import java.util.stream.Collectors; import com.alibaba.fastjson.JSON; public class SortTest { public static void main(String[] args) { List<Person> people = Arrays.asList(new Person("John", 20), // new Person("Sara", 20), // new Person("Jane", 18), // new Person("Greg", 35));// //按年龄升序排列 Collections.sort(people, new Comparator<Person>() { @Override public int compare(Person p1, Person p2) { return p1.getAge() - p2.getAge(); } }); System.out.println(people); //按年龄降序排列 people.sort(Comparator.comparingInt(Person::getAge).reversed()); System.out.println(people); //按年龄升序排列 people = people.stream() .sorted(Comparator.comparing(Person::getAge)) .collect(Collectors.toList()); System.out.println(people); //按年龄降序排列 people = people.stream() .sorted((p1, p2) -> Integer.valueOf(p2.getAge()).compareTo(Integer.valueOf(p1.getAge()))) .collect(Collectors.toList()); System.out.println(people); //按年龄升序、姓名降序排列 people = people.stream().sorted((p1, p2) -> { int ageCom = Integer.valueOf(p1.getAge()).compareTo(Integer.valueOf(p2.getAge())); int nameCom = p2.getName().compareToIgnoreCase(p1.getName()); if (ageCom == 0) { return nameCom; } return ageCom; }).collect(Collectors.toList()); System.out.println(people); Map<String, Object> mapA = new HashMap<>(); mapA.put("name", "John"); mapA.put("age", 20); Map<String, Object> mapB = new HashMap<>(); mapB.put("name", "Jane"); mapB.put("age", 18); Map<String, Object> mapC = new HashMap<>(); mapC.put("name", "Greg"); mapC.put("age", 35); Map<String, Object> mapD = new HashMap<>(); mapD.put("name", "Sara"); mapD.put("age", 21); List<Map<String, Object>> list = new ArrayList<>(); list.add(mapA); list.add(mapB); list.add(mapC); list.add(mapD); //按姓名升序排列 list.sort(new Comparator<Map<String, Object>>() { @Override public int compare(Map<String, Object> map1, Map<String, Object> map2) { return ((String) map1.get("name")).compareToIgnoreCase((String) map2.get("name")); } }); System.out.println(list); //按姓名降序排列 Collections.sort(list, new Comparator<Map<String, Object>>() { @Override public int compare(Map<String, Object> map1, Map<String, Object> map2) { return ((String) map1.get("name")).compareToIgnoreCase((String) map2.get("name")); } }.reversed()); System.out.println(list); //按姓名升序排列 list = list.stream().sorted(new Comparator<Map<String, Object>>() { @Override public int compare(Map<String, Object> map1, Map<String, Object> map2) { return ((String) map1.get("name")).compareToIgnoreCase((String) map2.get("name")); } }).collect(Collectors.toList()); System.out.println(list); //按姓名降序排列 list = list.stream().sorted((p1, p2) -> ((String) p2.get("name")).compareToIgnoreCase((String) p1.get("name"))).collect(Collectors.toList()); System.out.println(list); //多条件排序 list.remove(mapD); Map<String, Object> mapE = new HashMap<>(); mapE.put("name", "Greg"); mapE.put("age", 19); list.add(mapE); Collections.shuffle(list, new SecureRandom()); list.sort(new Comparator<Map<String, Object>>() { @Override public int compare(Map<String, Object> o1, Map<String, Object> o2) { //姓名升系 int nameC = String.valueOf(o1.get("name")).compareToIgnoreCase(String.valueOf(o2.get("name"))); //年龄降序 int ageC = ((Integer) o2.get("age")).compareTo((Integer) o1.get("age")); if (nameC == 0) { return ageC; } return nameC; } }); System.out.println(list); } } class Person { private String name; private int age; public Person(String theName, int theAge) { name = theName; age = theAge; } public String getName() { return name; } public int getAge() { return age; } public String toString() { return JSON.toJSONString(this); } }
在java8之前,对集合排序只能用Collections集合工具类的sort静态方法 public static <T> void sort(List<T> list, Comparator<? super T> c) {}
传入要排序的list和Comparator实例即可。Comparator接口有2个方法,int compare(T o1, T o2)和boolean equals(Object obj),由于所有类都继承了Object类,而Object已经实现了equals方法,所以Comparator接口相当于只有一个int compare(T o1, T o2)方法,那么就可以参考Runnable接口的思路,创建一个Comparator接口的匿名实现类,在匿名类中实现compare方法即可。
Comparator支持泛型,可以指定要排序元素的类型,这就有上例中的
//按年龄升序排列 Collections.sort(people, new Comparator<Person>() { @Override public int compare(Person p1, Person p2) { return p1.getAge() - p2.getAge(); } });
java1.8在List接口中新增了实例方法sort(Comparator<? super E> c),并提供了默认实现,只需要传入一个Comparator实例即可。此时的Comparator实例既可以用匿名内部类的方式,也可以用java8独有的方式。
1.java8在Comparator接口中新增了很多静态方法可以直接得到Comparator实例,有
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T, ? extends U> keyExtractor)
public static<T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor)
public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor)
public static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor)
还可以通过Comparator的reversed()实例方法对其进行反转,由升序转为降序或者由降序转为升序
于是就有了上例中的
people.sort(Comparator.comparingInt(Person::getAge));
2.利用java8在Collection接口中新增的stream()默认方法,把Collection对象转换成Stream对象,然后利用Stream的Stream<T> sorted(Comparator<? super T> comparator)实例方法,也是需要传入一个Comparator实例。
people = people.stream().sorted(Comparator.comparingInt(Person::getAge)).collect(Collectors.toList());
利用lambda表达式,Comparator实例也可通过下面方式获得 (p1,p2)->Integer.valueOf(p1.getAge()).compareTo(Integer.valueOf(p2.getAge()))
people = people.stream().sorted((p1,p2)->Integer.valueOf(p1.getAge()).compareTo(Integer.valueOf(p2.getAge()))).collect(Collectors.toList());
如果是多个排序条件的话,如按年龄升序、姓名升序排列,如下
people = people.stream().sorted(Comparator.comparingInt(Person::getAge).thenComparing(Person::getName)).collect(Collectors.toList());
按年龄升序、姓名降序排列,如下
people = people.stream().sorted((p1, p2) -> { int ageCom = Integer.valueOf(p1.getAge()).compareTo(Integer.valueOf(p2.getAge())); int nameCom = p2.getName().compareToIgnoreCase(p1.getName()); if (ageCom == 0) { return nameCom; } return ageCom; }).collect(Collectors.toList());
List中元素不是自定义类而是Map时,排序方法也是差不多的,唯一的不同就是只能用lambda表达式创建Comparator实例,而用Comparator的静态方法创建的实例则不能用。