我想按日期对从数据库中获取的对象列表进行排序。问题是日期(table1,table2)的位置取决于ObjectType
。如果是1,则应从第一个表中选择日期,如果它是2,则从第二个表中选择。我开始是这样的:
objectList.stream().sorted((h1,h2)->
if(h1.getObjectType().getId()==1){
h1.getObject().getTable1().getTime()}//here is the problem
);
但后来我感到困惑,因为在if
条款之后我不能只添加.compareTo
。有没有办法使用带有if
子句的lambda表达式来生成Java 8比较器?
答案 0 :(得分:8)
这里有一些事情在发生。
首先,如果你想在lambda中使用if-else
语句,你需要使用语句lambda (带括号的那种)而不是表达式lambda (省略了大括号)。使用语句lambda,您必须显式使用return
语句,而在表达式lambda中,返回值隐式只是评估表达式的结果。
您有一些条件逻辑用于选择要比较的值。我假设这个逻辑需要独立地应用于被比较的两个对象中的每一个,这意味着直接的进行方式将要求你写出两次逻辑。
最后,您需要为实际比较编写一些逻辑。
对于此示例,我假设正在排序的对象属于Obj
类型,并且他们要对其进行排序的值属于ObjDate
类型,而我{&#39}。进一步假设彼此相当。 (也就是ObjDate implements Comparable<ObjDate>
。)我还假设对象id是1或2,所以我不会处理值为其他的情况。
这是一个使用语句lambda:
的完全写出的比较器 objectList.stream().sorted((h1, h2) -> {
ObjDate h1date;
ObjDate h2date;
if (h1.getObjectType().getId() == 1) {
h1date = h1.getObject().getTable1().getTime();
} else {
h1date = h1.getObject().getTable2().getTime();
}
if (h2.getObjectType().getId() == 1) {
h2date = h2.getObject().getTable1().getTime();
} else {
h2date = h2.getObject().getTable2().getTime();
}
return h1date.compareTo(h2date);
});
唉!编写比较器很有趣,不是吗? : - )
基本上,我们的想法是应用get-from-table1-or-table2逻辑为第一个对象提取正确的值,然后对第二个对象提取相同的值。最后,返回比较它们的结果。
这样可行,但这里有一些明显重复的代码。公共代码可以称为密钥提取器,因为给定要比较的对象,它提取用作比较基础的密钥。这是一个关键的提取器方法,它为单个对象执行此操作:
ObjDate getSortingDate(Obj obj) {
if (obj.getObjectType().getId() == 1) {
return obj.getObject().getTable1().getTime();
} else {
return obj.getObject().getTable2().getTime();
}
}
现在我们有了这个,我们可以大大简化比较器:
objectList.stream().sorted((h1, h2) -> {
ObjDate h1date = getSortingDate(h1);
ObjDate h2date = getSortingDate(h2);
return h1date.compareTo(h2date);
});
如果我们折叠局部变量,我们可以将它转换为表达式lambda:
objectList.stream().sorted(
(h1, h2) -> getSortingDate(h1).compareTo(getSortingDate(h2)));
最后,从两个对象中提取密钥并比较它们的想法在比较器中是如此常见,以至于有一个辅助方法可以为您执行此操作:Comparator.comparing(keyExtractor)
。给定两个对象,它在两个对象上运行键提取器并比较它们。 (更确切地说,它返回一个执行此操作的函数。)我们可以直接使用它来进一步简化:
objectList.stream().sorted(Comparator.comparing(this::getSortingDate));
答案 1 :(得分:0)
由于有多行代码,因此在lambda表达式中需要一个块。如果你的lambda中有一个块,你需要返回一些东西。