Java中List的排序


場景

Bean定義如下,僅有一個類型為Integerage字段。

@NoArgsConstructor
@AllArgsConstructor(staticName = "of")
@Data
public static class Employee {
    private Integer age;
}     

列表初始化5個元素:

List<Employee> list = new ArrayList<>();
list.add(Employee.of(21));
list.add(Employee.of(22));
list.add(Employee.of(25));
list.add(Employee.of(28));
list.add(Employee.of(23));           

排序

使用Collections中的sort方法進行排序:

Collections.sort(list, new Comparator<Employee>() {
    @Override
    public int compare(Employee o1, Employee o2) {
        return o1.getAge().compareTo(o2.getAge());
    }
});

倒序:

Collections.reverse(list);

lambda表達式

JDK8支持lambda表達式,寫法更加簡潔:

Collections.sort(list, (o1, o2) -> o1.getAge().compareTo(o2.getAge()));

或者使用Comparator接口:

Collections.sort(list, Comparator.comparing(Employee::getAge));

倒序:

Collections.sort(list, Comparator.comparing(Employee::getAge).reversed());

stream的sorted方法

list.stream().sorted(Comparator.comparing(Employee::getAge));

倒序:

list.stream().sorted(Comparator.comparing(Employee::getAge).reversed());

list自帶的sort方法

list.sort(Comparator.comparing(Employee::getAge));

倒序:

list.sort(Comparator.comparing(Employee::getAge).reversed());

null值

假設列表中有age字段為null:

List<Employee> list = new ArrayList<>();
list.add(Employee.of(21));
list.add(Employee.of(null));
list.add(Employee.of(null));
list.add(Employee.of(28));
list.add(Employee.of(23));           

這個時候會報NPE:

-----------------------------
Exception in thread "main" java.lang.NullPointerException
	at java.util.Comparator.lambda$comparing$77a9974f$1(Comparator.java:469)
	at java.util.TimSort.countRunAndMakeAscending(TimSort.java:355)
	at java.util.TimSort.sort(TimSort.java:220)
	at java.util.Arrays.sort(Arrays.java:1512)
	at java.util.ArrayList.sort(ArrayList.java:1462)

可以使用Comparator.comparing的第2個參數:

list.sort(Comparator.comparing(Employee::getAge, Comparator.nullsLast(Comparator.naturalOrder())));
list.sort(Comparator.comparing(Employee::getAge, Comparator.nullsLast(Integer::compareTo)));
list.sort(Comparator.comparing(Employee::getAge, Comparator.nullsLast(Comparable::compareTo)));

以上3中寫法都可以,注意第2個參數使用了Comparator.nullsLast讓null排在最后。
與之對應的是Comparator.nullsFirst可以null排在最前。

任意字段排序

最近項目中有個這樣場景,List中是個Map<String, Object>,需要支持Map的任意key排序。
完整代碼如下:

import java.util.*;

/**
 * @author cdfive
 * @date 2019-05-26
 */
public class ListSortDemo2 {
    public static void main(String[] args) {
        List<Map<String, Object>> list = new ArrayList<>();
        list.add(new HashMap<String, Object>(){{put("name", "aaa");put("age", 21);}});
        list.add(new HashMap<String, Object>(){{put("name", "ccc");put("age", null);}});
        list.add(new HashMap<String, Object>(){{put("name", "ddd");put("age", null);}});
        list.add(new HashMap<String, Object>(){{put("name", "bbb");put("age", 28);}});
        list.add(new HashMap<String, Object>(){{put("name", "aaa");put("age", 23);}});

        printList(list);

        printLineSep();

        sort(list, "age", "asc");

        printList(list);
    }

    public static void sort(List<Map<String, Object>> list, String sortField, String sortDirection) {
        if ("desc".equals(sortDirection)) {
            Comparator<Map<String, Object>> comparator = Comparator.comparing(o -> (Comparable) o.get(sortField), Comparator.nullsFirst(Comparable::compareTo));
            list.sort(comparator.reversed());
        } else {
            Comparator<Map<String, Object>> comparator = Comparator.comparing(o -> (Comparable) o.get(sortField), Comparator.nullsLast(Comparable::compareTo));
            list.sort(comparator);
        }
    }

    public static void printList(List<?> list) {
        list.stream().forEach(o -> System.out.print(o));
        System.out.println();
    }

    public static void printLineSep() {
        System.out.println("-----------------------------");
    }
}

注意:
倒序使用Comparator.nullsFirstcomparator.reversed(),需要單獨定義comparator變量,如果直接一行寫:
list.sort(Comparator.comparing(o -> (Comparable) o.get(sortField), Comparator.nullsFirst(Comparable::compareTo)).reversed());會編譯不通過。
正序使用Comparator.nullsLast

正序null在后面,倒序null在前面,可以這樣寫:

public static void sort2(List<Map<String, Object>> list, String sortField, String sortDirection) {
    Comparator<Map<String, Object>> comparator = Comparator.comparing(new Function<Map<String, Object>, Comparable>() {
        @Override
        public Comparable apply(Map<String, Object> map) {
            Object obj = map.get(sortField);

            if (obj instanceof Comparable) {
                return (Comparable) obj;
            }

            if (obj == null) {
                return null;
            }

            throw new UnsupportedOperationException("無法排序的字段=" + sortField);
        }
    }, Comparator.nullsLast(Comparator.naturalOrder()));

    if ("desc".equals(sortDirection)) {
        list.sort(comparator.reversed());
    } else {
        list.sort(comparator);
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM