为什么Java不能检查这段代码?

时间:2017-12-23 13:04:31

标签: java generics typechecking

我有一些流处理代码,它接受单词流并对它们执行一些操作,然后将它们缩减为Map,其中包含单词作为键,单词的出现次数为{{1}价值。为了简化代码,我使用了jOOL library' Seq类,其中包含许多有用的快捷方法。

如果我这样编写代码就编译得很好:

Long

但是,如果我尝试用更自我记录的item.setWordIndex ( getWords (item) // returns a Seq<String> .map (this::removePunctuation) // String -> String .map (stemmer::stem) // String -> String .groupBy(str -> str, Collectors.counting ())); 替换str -> str lambda,我会收到以下错误:

  

Function::identity类型中的方法setWordIndex(Map<String,Long>)不适用于参数MyClass
  类型(Map<Object,Long>)未定义此处适用的Function

为什么identity(String)Function::identity的行为有任何不同,我(或许是天真地)假设它是直接等价的,为什么编译器在使用它时可以处理它?<​​/ p >

(是的,我知道我可以通过将先前的str -> str应用程序移动到map操作来删除身份功能,但我发现代码更清晰,因为它遵循应用程序逻辑更直接)

2 个答案:

答案 0 :(得分:7)

您希望Function.identity()(返回Function<T, T>),而不是Function::identity(与SAM类型Supplier<Function<T, T>>匹配)。

以下代码编译良好:

static String removePunctuation(String x) { return x; }
static String stem(String x) { return x; }

// ...

final Map<String, Long> yeah = Seq.of("a", "b", "c")
        .map(Test::removePunctuation)
        .map(Test::stem)
        .groupBy(Function.identity(), Collectors.counting());

答案 1 :(得分:2)

两种类型之间略有不同;它们不是直接等同的:

  • Function.identity()必须返回输入类型,因为其类型为Function<T, T>;
  • str -> str可以返回更广泛的类型;实际上是Function<? extends T, T>