如何在java中使用带条件的比较器
我试图根据从API收到的排序键和排序顺序对列表进行排序。 例如 我有一个带有sortkey和sortorder的列表,我需要根据它进行排序如何在java中使用带条件的比较器,java,java-8,comparator,Java,Java 8,Comparator,我试图根据从API收到的排序键和排序顺序对列表进行排序。 例如 我有一个带有sortkey和sortorder的列表,我需要根据它进行排序 List<SortList> sortlist; 但是我需要在一个条件下检查sortfeild,并基于该条件,只考虑对字段进行排序 例: 如果(sortkey=“name”) 按排序顺序从sortlist中选择SortByTatKey 如果(sortkey=“地点”) SortByth按排序顺序从sortlist中选择键 所以在这里,如果sor
List<SortList> sortlist;
但是我需要在一个条件下检查sortfeild,并基于该条件,只考虑对字段进行排序
例:
如果(sortkey=“name”)
按排序顺序从sortlist中选择SortByTatKey
如果(sortkey=“地点”)
SortByth按排序顺序从sortlist中选择键
所以在这里,如果sortlist同时具有名称和位置,那么它应该按键和顺序进行排序
你知道我怎样才能做到这一点吗
排序列表包含:
{
"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();
}
}
虽然你也可以自己写,但我发现最好是授权“标准”部分,只写与此不同的部分
如果您发现自己有许多这样的排序键,那么更合适的方法是使用映射:
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();
}
}
private static final Map COMPARE\u Map=new HashMap(){{
put.(“name”,Comparator.comparing(Employee::getName));
put.(“place”,Comparator.comparing(Employee::getPlace));
}});
公共比较器getComparator(字符串排序键){
如果(比较地图容器(排序键)){
返回COMPARE_MAP.get(sortKey);
}否则{
抛出新的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
来存储每个可能键的所有对应比较器:
HashMap<String, Comparator<Employee>> comparators = new HashMap<>();
comparators.put("name", Comparator.comparing(Employee::getName));
comparators.put("age", Comparator.comparing(Employee::getAge));
// ...
正如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));
sortlist.stream().map(sc->{
Comparator c=comparators.get(sc.getKey());
返回sc.getOrder().equals(“DESC”)?c.reversed():c;
}).reduce(比较器::然后比较)
.ifPresent(x->Collections.sort(originalist,x));
如果两个元素具有不同的sortkey
s,您需要它如何工作?@Marv:实际上,sortkey和order将由外部提供。那么,是否应该基于排序键和排序顺序来链接排序?您能否举例说明sortlist
可能包含哪些内容?@Sweeper添加了……在这里,我如何确定排序顺序,来自请求的排序顺序可能包含DESC和ASC,那么如何基于此进行排序?它也会像将它们链接在一起一样工作吗?对于这类事情,使用映射
要干净得多。@chrylis是真的,事实上,如果我必须在这里再添加一个,我肯定会使用映射。我会相应地调整我的答案。@Neil:在这里,我如何添加排序器,因为我还需要检查排序器并使用映射进行排序是一种干净的方法,创建HashMap
的子类只是为了在源代码中保存几个字符,而不是。此外,put.(
甚至不是有效语法。为什么第一个get(0)case是在for循环之外给出的?它不是在检查ASC case,对吗?@karthikcherukunumal第一个case是特殊的,因为您需要调用比较
,而不是然后比较
。我假设如果它不是递减的,它是递增的。好的,但是对于第二个case,我们是在与Comparator进行比较。比较(Employee::getName)对吗?这样行吗?循环体中有大量代码重复。另一个局部变量如何?Comparator next=comparators.get(i.getKey());if(sortlist.get(i.getOrder().equals(“DESC”){next=Comparator.reversed();}Comparator=Comparator.thencaring(next)
或者使用流API进行简化:sortlist.Stream().map(sc->{Comparator c=comparators.get(sc.getKey());return sc.getOrder().equals(“DESC”)?c.reversed():c;})。reduce(Comparator::thenparating)。if present(theList::sort);
而不是x->Collections.sort(originalList,x)
您还可以使用x->originalList.sort(x)
,这相当于originalList::sort
…
class SortCritera {
private String key;
private String order;
public String getKey() {
return key;
}
public String getOrder() {
return order;
}
// constructors, setters...
}
HashMap<String, Comparator<Employee>> comparators = new HashMap<>();
comparators.put("name", Comparator.comparing(Employee::getName));
comparators.put("age", Comparator.comparing(Employee::getAge));
// ...
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".
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));