下面是我专门编写的代码,用于在 Java 8 Stream
中使用自定义 Comparator
和 max
。
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
。
我到底做错了什么?
补充说明 (04/24/14):
我现在明白语法错误的原因了。谢谢。
这里真的需要自定义
Comparator
吗?
因为 BigDecimal
实现了 Comparable
但没有似乎实现了 Comparator
(它有 CompareTo( )
但没有 Compare()
) 我认为自定义Comparator
是必要的。这就是为什么我不能只使用 Comparator.comparing(ft -> ft.value)
的原因。我的逻辑有问题吗?
最佳答案
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
接口(interface),你可以这样做:
public class forTest implements Comparable<forTest> {
@Override
public int compareTo(forTest other) {
return this.value.compareTo(other.value);
}
...
}
在 Comparable 上使用 max() 的方法是:
.max(Comparator.naturalOrder())
两个样式注释:
我强烈反对在
Optional
的实例上使用orElse(null)
。这是允许的,尽管它的主要目的可能是将新 Java 8 API 的使用改造成期望 null 以指示缺少值的代码。如果可能,请避免使用orElse(null)
,因为这会强制调用者检查 null。取而代之的是,用一个实际值来替换不存在的值,或者将Optional
本身返回给调用者,这样调用者就可以应用它想要的任何策略。我建议坚持使用大写混合大小写类名的既定 Java 命名约定。类名
forTest
和forTestComparator
使这段代码有点难以使用,因为它们看起来不像类名。
关于java - 使用自定义比较器的最大流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23259318/