【问题标题】:Why does stream sorted() have trouble inferring my type?为什么流 sorted() 无法推断我的类型?
【发布时间】:2016-04-17 11:55:42
【问题描述】:

我正在阅读 this article 并尝试计算文本文件中的一些单词,发现我无法像文章的清单 1 中显示的那样反向排序。

我有一些代码可以工作:

public class WordCounter {
    public static final PrintWriter out = new PrintWriter(System.out, true);

    public static void main(String... args) throws IOException {
        //The need to put "", in front of args in the next line is frustrating.
        try (Stream<String> lines = Files.lines(Paths.get("", args))) {
            lines.parallel()
              .map(l -> l.toLowerCase().replaceAll("[^a-z\\s]", "").split("\\s"))
              .flatMap(Arrays::stream)
              .filter(s -> !s.isEmpty())
              .collect(Collectors.groupingBy(
                      Function.identity(), Collectors.counting()))
                // Sort Map<K,V> Entries by their Integer value descending
                .entrySet().parallelStream()
// MY QUESTION IS ABOUT THIS METHOD:
                  .sorted(
                    Comparator.comparing(Map.Entry::getValue, Comparator.reverseOrder()))
// --------------------------------- //
                  .forEachOrdered(e -> out.printf("%5d\t%s\n", e.getValue(), e.getKey()));
        }
        out.close();
    }
}

所以文章会建议这一行:

.sorted(Comparator.comparing(Map.Entry::getValue, Comparator.reverseOrder()))

可以写成:

.sorted(Comparator.comparing(Map.Entry::getValue).reversed())

尽管如此,Java 编译器抱怨说:

错误:(46, 49) java: 无效的方法引用非静态方法 getValue() 不能从静态上下文中引用

两个comparing 方法签名具有完全相同的第一个参数和静态范围,但前者有效,而后者抱怨getValue 是非静态的。

我最初的想法是把它写成:

.sorted(Map.Entry.comparingByValue())

编译并运行但不反转。或如:

.sorted(Map.Entry.comparingByValue().reversed())

再次无法编译,给出错误消息:

错误:(48, 62) java: 不兼容的类型: java.util.Comparator> 无法转换为 java.util.Comparator>

好的,那应该是:

.sorted(Map.Entry.<String, Long>comparingByValue().reversed())

哪个有效。

我似乎看不出如何在“可以写为”行中为 Map.Entry::getValue 表单提供类似的泛型类型规范。

【问题讨论】:

  • “我似乎看不出如何为 Map.Entry::getValue 表单提供类似的泛型类型规范。” Map.Entry&lt;String,Long&gt;::getValue 不幸的是,类型推断仍然有限制。
  • @Radiodef 谢谢;因此,我的 IDE(IDEA CE 15)将此处的 getValue 突出显示为红色,并抱怨未找到对方法的引用。但是它编译和运行正确,这意味着 IDEA 使用的内部 Java 编译或语法检查器与实际 Java 不一致。
  • 那可能是一个 IntelliJ 错误。我也不知道为什么它会在一种情况下给你一个“静态上下文”错误消息。
  • @Radiodef 如果您这样填写,我很乐意接受您的回答。它确实回答了我的问题。

标签: java java-stream


【解决方案1】:

至于为什么会发生这种情况:虽然 Java 8 中的类型推断取得了突飞猛进的发展,但如果返回值被分配给某个东西,它仍然只会使用返回目标类型。

在 Java 7 中,我们只能在 赋值上下文(使用 =)中使用它,而且它有点笨拙。在 Java 8 中,它不那么笨重,我们可以在 调用上下文 中使用它(作为方法参数传递,将其分配给形参)。

所以按照我的理解,如果方法调用没有在赋值上下文或调用上下文中使用,目标类型推断就会关闭,因为它不再是所谓的 poly 表达式 ( 15.1218.5.2)。 JLS 也是这么说的。

简而言之,目标类型推断仅在返回值为:

  • 使用= 直接分配给变量,如v = foo();
  • 直接传递给方法,如bar(foo())

一旦你链接一个方法调用,比如v = foo().zap(),它就会停止工作。


从我的评论中删除:

我似乎看不出如何为Map.Entry::getValue 表单提供类似的泛型类型规范。

这将是Map.Entry&lt;String, Long&gt;::getValue

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多