为了账号安全,请及时绑定邮箱和手机立即绑定

如何在java中使用带条件的比较器

如何在java中使用带条件的比较器

饮歌长啸 2023-04-19 16:35:15
我正在尝试根据从 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 按排序顺序所以在这里,如果排序列表同时具有名称和位置,那么它应该同时按键和顺序排序知道我怎么能做到这一点?排序列表包含:{    "sortKey":"name",    "sortOrder":"ASC"},{    "sortKey":"place",    "sortOrder":"DESC"}要求是像 SQL 中的 ORDER BY 一样将它们链接在一起
查看完整描述

2 回答

?
互换的青春

TA贡献1797条经验 获得超6个赞

假设这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));


查看完整回答
反对 回复 2023-04-19
?
大话西游666

TA贡献1817条经验 获得超14个赞

您可以创建一个方法,当传递排序键时,您可以提供适当的比较器:


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 的哪些字段可用于排序。


查看完整回答
反对 回复 2023-04-19
  • 2 回答
  • 0 关注
  • 122 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信