Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在java中使用带条件的比较器_Java_Java 8_Comparator - Fatal编程技术网

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

如何在java中使用带条件的比较器,java,java-8,comparator,Java,Java 8,Comparator,我试图根据从API收到的排序键和排序顺序对列表进行排序。 例如 我有一个带有sortkey和sortorder的列表,我需要根据它进行排序 List<SortList> sortlist; 但是我需要在一个条件下检查sortfeild,并基于该条件,只考虑对字段进行排序 例: 如果(sortkey=“name”) 按排序顺序从sortlist中选择SortByTatKey 如果(sortkey=“地点”) SortByth按排序顺序从sortlist中选择键 所以在这里,如果sor

我试图根据从API收到的排序键和排序顺序对列表进行排序。 例如 我有一个带有sortkey和sortorder的列表,我需要根据它进行排序

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));