以下是我专门编写的代码,用于在Java 8 Comparator
中使用自定义max
和Stream
。
import java.math.BigDecimal;
import java.util.*;
public class BigDecimalMax {
public static BigDecimal getBigDecimalMax(List<forTest> list) {
return list.stream()
.filter(t -> t.id % 2 == 0)
.max(forTestComparator::compare) //<-- syntax error ----------
.orElse(null);
}
public static class forTestComparator implements Comparator<forTest> {
@Override
public int compare(forTest val1, forTest val2) {
return val1.value.compareTo(val2.value);
}
}
public static void main(String[] args) {
List<forTest> lst = new ArrayList<>();
Random rn = new Random();
BigDecimalMax bdm = new BigDecimalMax();
for (int i=1; i<22; ++i) {
lst.add(bdm.new forTest(i, BigDecimal.valueOf(rn.nextLong())));
}
System.out.println(getBigDecimalMax(lst));
}
class forTest {
public int id;
public BigDecimal value;
forTest(int id, BigDecimal value) {
this.id = id;
this.value = value;
}
@Override
public String toString() {
return "forTest{" +
"id=" + id +
", value=" + value +
'}';
}
}
}
我在方法参考上遇到语法错误,我不明白。
Error:(15, 18) java: incompatible types: invalid method reference
cannot find symbol
symbol: method compare(BigDecimalMax.forTest, BigDecimalMax.forTest)
location: class BigDecimalMax.forTestComparator
虽然IntelliJ IDEA抱怨Non-static method cannot be referenced from a static context
。
我到底错在了什么?
其他解释(2014年4月24日):
我现在明白了语法错误的原因。谢谢。
这里实际需要自定义Comparator
吗?
由于BigDecimal
实施Comparable
但不似乎实施Comparator
(它有CompareTo()
但没有 Compare()
)我认为自定义Comparator
是必要的。这就是我不能只使用Comparator.comparing(ft -> ft.value)
的原因。我的逻辑有缺陷吗?
答案 0 :(得分:12)
Sotirios Delimanolis' answer展示了如何解决问题,但我还有一些事情需要补充。
如果您已经有一个实现Comparator的类,则不需要对其compare()方法使用方法引用。您可以直接传递它的实例,因为max()接受对比较器的引用:
.max(new forTestComparator())
或
forTestComparator instance = new forTestComparator();
...
.max(instance)
但是,Comparator上的组合器函数通常不需要有一个实现Comparator的类。例如,您可以完全摆脱forTestComparator
类,只需执行此操作:
.max(Comparator.comparing(ft -> ft.value))
或如果forTest
有明显的getValue()方法,可以按如下方式重写流max()调用:
.max(Comparator.comparing(forTest::getValue))
此外,如果您想让forTest
实现Comparable
界面,您可以这样做:
public class forTest implements Comparable<forTest> {
@Override
public int compareTo(forTest other) {
return this.value.compareTo(other.value);
}
...
}
在Comparable上使用max()的方法是:
.max(Comparator.naturalOrder())
两种风格的笔记:
我强烈反对在orElse(null)
的实例上使用Optional
。这是允许的,尽管它的主要目的可能是将新的Java 8 API改造成代码,这些代码期望为空以表示缺少值。如果可能,请避免orElse(null)
,因为这会强制调用者检查null。相反,用实际值替换替换缺席值,或者将Optional
本身返回给调用者,这样调用者就可以应用他们想要的任何策略。
我建议坚持大写的混合大小写类名称的既定Java命名约定。类名forTest
和forTestComparator
使得此代码难以使用,因为它们不像某些类名一样
答案 1 :(得分:6)
forTestComparator#compare
是一种实例方法。您需要实例方法参考,而不是您拥有的static
方法参考。
像
这样的东西new forTestComparator()::compare
或漫长的路(你的班级没有实例状态,所以你真的不关心参考)
forTestComparator instance = new forTestComparator(); // fix for Java conventions
return list.stream()
.filter(t -> t.id % 2 == 0)
.max(instance::compare) //<-- syntax error ----------
.orElse(null);
请参阅方法参考here的Java教程。
引用特定对象
的实例方法-> ContainingObject::instanceMethodName
旁注,这个
return list.stream()
.filter(t -> t.id % 2 == 0)
.max(new forTestComparator()::compare)
.orElse(null);
以forTest
值解析。您需要更改方法的返回类型。