簡體   English   中英

如何在java中使用帶有條件的比較器

[英]How to use Comparator with conditions in java

我正在嘗試根據從 API 收到的排序鍵和排序順序對列表進行排序。 例如,我有一個帶有 sortkey 和 sortorder 的列表,我需要根據它進行排序。

List<SortList> sortlist;

我有一個對象列表:

List<Employee> employee;

我可以使用排序

Collections.sort(sourceList, Comparator
                .comparing(Employee::getAge).reversed()
                .thenComparing(Employee::getCount));

但我需要在條件下檢查 sortfeild,並基於此僅考慮對字段進行排序。

前任:

if(sortkey = "name") sortbythatkey from sortlist 按排序順序

if (sortkey = "place") sortbythat key from sortlist 按排序順序

所以這里如果 sortlist 有 name 和 place 那么它應該按鍵和順序排序

知道我怎么能做到這一點嗎?

排序列表包含:

{
    "sortKey":"name",
    "sortOrder":"ASC"

},
{
    "sortKey":"place",
    "sortOrder":"DESC"

}

要求是將它們像 SQL 中的 ORDER BY 一樣鏈接在一起

您可以創建一個方法,當傳遞排序鍵時,您提供適當的比較器:

public Comparator<Employee> getComparator(String sortKey) {
    if("name".equals(sortKey)) {
        return Comparator.comparing(Employee::getName);
    } else if ("place".equals(sortKey) {
        return Comparator.comparing(Employee::getPlace);
    } else {
        throw new IllegalArgumentException();
    }
}

稱之為它只是:

Collections.sort(sourceList, getComparator(sortKey).reversed()
                .thenComparing(Employee::getCount));

雖然您也可以自己編寫,但我發現委托“標准”部分並簡單地編寫與此不同的部分會更好。

如果您發現自己有很多這樣的排序鍵,那么更合適的方法是使用映射:

private static final Map<String, Comparator<Employee>> COMPARE_MAP = new HashMap<>() {{
    put.("name", Comparator.comparing(Employee::getName));
    put.("place", Comparator.comparing(Employee::getPlace));
}});

public Comparator<Employee> getComparator(String sortKey) {
    if(COMPARE_MAP.containsKey(sortKey)) {
        return COMPARE_MAP.get(sortKey);
    } else {
        throw new IllegalArgumentException();
    }
}

反射也是一種選擇,但我會謹慎使用反射,除非這樣做變得不切實際。 在這種情況下,您可以創建自己的注釋來確定 Employee 類的哪些字段可用於排序。

假設sortlist的列表SortCriteria ,這是這樣一個類:

class SortCritera {
    private String key;
    private String order;

    public String getKey() {
        return key;
    }

    public String getOrder() {
        return order;
    }

    // constructors, setters...
}

您首先需要一個HashMap<String, Comparator<Employee>>來存儲每個可能鍵的所有相應比較器:

HashMap<String, Comparator<Employee>> comparators = new HashMap<>();
comparators.put("name", Comparator.comparing(Employee::getName));
comparators.put("age", Comparator.comparing(Employee::getAge));
// ...

然后你可以遍歷sortlist並繼續調用thenComparing

Comparator<Employee> comparator = comparators.get(sortlist.get(0).getKey());
if (sortlist.get(0).getOrder().equals("DESC")) {
    comparator = comparator.reversed();
}
for(int i = 1 ; i < sortlist.size() ; i++) {
    if (sortlist.get(i).getOrder().equals("DESC")) {
        comparator = comparator.thenComparing(comparators.get(sortlist.get(i).getKey()).reversed());
    } else {
        comparator = comparator.thenComparing(comparators.get(sortlist.get(i).getKey()));
    }
}
// now you can sort with "comparator".

正如 Holger 所建議的,您也可以使用 Stream API 來執行此操作:

sortlist.stream().map(sc -> {
    Comparator<Employee> c = comparators.get(sc.getKey()); 
    return sc.getOrder().equals("DESC")? c.reversed(): c; 
}).reduce(Comparator::thenComparing)
.ifPresent(x -> Collections.sort(originalList, x));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM