Java 8 个带有 if 子句的比较器
Java 8 comparator with if clause
我想按日期对从数据库中获取的对象列表进行排序。问题是日期 (table1,table2) 的位置取决于 ObjectType
。如果它是 1,那么应该从第一个 table 中选择日期,如果是 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 比较器?
由于有多行代码,您的 lambda 表达式中需要一个块。如果你的 lambda 中有一个块,你需要 return 一些东西。
这里同时发生了一些事情。
首先,如果你想在lambda内部使用if-else
语句,你需要使用语句lambda(带大括号的那种) 表达式 lambda(其中省略了大括号)。对于语句 lambda,您必须显式使用 return
语句,而在表达式 lambda 中,return 值隐式地只是计算表达式的结果。
您有一些条件逻辑来选择要比较的值。我假设这个逻辑需要独立地应用到被比较的两个对象中的每一个,所以这意味着直接的方法将需要你写出逻辑两次。
最后,你需要写一些实际比较的逻辑。
对于这个例子,我假设被排序的对象是 Obj
类型,并且它们被排序的值是 ObjDate
类型,我将进一步假设可以相互比较。 (也就是说,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 逻辑为第一个对象提取正确的值,然后对第二个对象进行同样的操作。最后,return他们比较的结果。
这会起作用,但这里有一些明显的重复代码。通用代码可以称为 key extractor 因为给定一个要比较的对象,它会提取一个键作为比较的基础。这是针对单个对象执行此操作的密钥提取器方法:
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)
。给定两个对象,这将在两个对象上运行密钥提取器并比较它们。 (更准确地说,它 return 是一个执行此操作的函数。)我们可以直接使用它来进一步简化事情:
objectList.stream().sorted(Comparator.comparing(this::getSortingDate));
我想按日期对从数据库中获取的对象列表进行排序。问题是日期 (table1,table2) 的位置取决于 ObjectType
。如果它是 1,那么应该从第一个 table 中选择日期,如果是 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 比较器?
由于有多行代码,您的 lambda 表达式中需要一个块。如果你的 lambda 中有一个块,你需要 return 一些东西。
这里同时发生了一些事情。
首先,如果你想在lambda内部使用if-else
语句,你需要使用语句lambda(带大括号的那种) 表达式 lambda(其中省略了大括号)。对于语句 lambda,您必须显式使用 return
语句,而在表达式 lambda 中,return 值隐式地只是计算表达式的结果。
您有一些条件逻辑来选择要比较的值。我假设这个逻辑需要独立地应用到被比较的两个对象中的每一个,所以这意味着直接的方法将需要你写出逻辑两次。
最后,你需要写一些实际比较的逻辑。
对于这个例子,我假设被排序的对象是 Obj
类型,并且它们被排序的值是 ObjDate
类型,我将进一步假设可以相互比较。 (也就是说,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 逻辑为第一个对象提取正确的值,然后对第二个对象进行同样的操作。最后,return他们比较的结果。
这会起作用,但这里有一些明显的重复代码。通用代码可以称为 key extractor 因为给定一个要比较的对象,它会提取一个键作为比较的基础。这是针对单个对象执行此操作的密钥提取器方法:
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)
。给定两个对象,这将在两个对象上运行密钥提取器并比较它们。 (更准确地说,它 return 是一个执行此操作的函数。)我们可以直接使用它来进一步简化事情:
objectList.stream().sorted(Comparator.comparing(this::getSortingDate));