java - 使用自定义比较器的最大流

标签 java max java-8 comparator java-stream

下面是我专门编写的代码,用于在 Java 8 Stream 中使用自定义 Comparatormax

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

  1. 我现在明白语法错误的原因了。谢谢。

  2. 这里真的需要自定义 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())

两个样式注释:

  1. 我强烈反对在 Optional 的实例上使用 orElse(null)。这是允许的,尽管它的主要目的可能是将新 Java 8 API 的使用改造成期望 null 以指示缺少值的代码。如果可能,请避免使用 orElse(null),因为这会强制调用者检查 null。取而代之的是,用一个实际值来替换不存在的值,或者将 Optional 本身返回给调用者,这样调用者就可以应用它想要的任何策略。

  2. 我建议坚持使用大写混合大小写类名的既定 Java 命名约定。类名 forTestforTestComparator 使这段代码有点难以使用,因为它们看起来不像类名。

关于java - 使用自定义比较器的最大流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23259318/

相关文章:

jquery:设置选项类型编号中的最小最大输入

java 8并行流问题

java - 我在 hashmap 上的 for 循环出错

java - 虽然构造函数需要参数我仍然可以在没有它们的情况下调用它

java - VHD Java 库

c++ - 有没有办法限制 STL::map 容器的最大大小?

java - 如何从ubuntu终端启动JBoss 6.1.0服务器?

MySQL - 在 MAX 时间戳上左连接

java - 识别当前正在处理的元素

java - 如何找到 Java8 方法引用的目标?