Scala的Collectors.groupingBy()替代方案

时间:2015-02-19 15:13:13

标签: java scala collectors

在Java中我有类似的东西:

Collectors.groupingBy((Re r) -> return r.pName)

它运作正常。现在我试图将同样的东西放到scala中,例如:

Collectors.groupingBy((r:Re) => return r.pName)

然后我得到像

这样的东西
cannot resolve reference groupingBy with such signature
cannot resolve symbol groupingBy

unspecified value parameters Collector
unspecified value parameters Supplier

如果您需要更多信息/代码,请告诉我,并且我会创建一些虚拟示例,因为我不允许发布确切的代码。

更新基于@Vladimir Matveev回答:

pName应该是String,但如果我写new java.util.function.Function[Re, java.lang.String],那么我得到一个

type mismatch;
 found   : java.util.function.Function[Re,String]
 required: java.util.function.Function[_ >: Re, _ <: ?0(in value x$1)(in value x$1)(in value x$1)(in value x$1)]

1 个答案:

答案 0 :(得分:3)

Java lambdas是任意函数接口的“实现者”(在这种特殊情况下Collectors.groupingBy()接受java.util.function.Function。然而,Scala匿名函数是某些类实现scala.FunctionX特征的实例。 ,你不能将Scala函数用于任意函数接口(但据我所知,有计划允许这样做。)

您需要创建一个明确扩展java.util.function.Function的匿名类:

Collectors.groupingBy(new java.util.function.Function[Re, ???] {
  def apply(r: Re) = r.pName
})

(当然,您需要输入正确类型的pName而不是???。)

如果您经常这样做,可以为Scala的T => U定义到java.util.function.Function[T, U]的隐式转换:

implicit class FunctionWrapper[T, U](f: T => U) extends java.util.function.Function[T, U] {
  def apply(x: T): U = f(x)
}

然后(假设这隐含在范围内)你可以像最初尝试过一样使用它:

Collectors.groupingBy((r: Re) => r.pName)

更新我不知道你的错误发生的原因(可能是因为Scala和Java泛型之间存在一些不兼容性),但是如果明确指定所有类型它确实有效:

scala> Collectors.groupingBy[Re, String](new JFunction[Re, String] {
     |   def apply(r: Re) = r.pName
     | })
res2: java.util.stream.Collector[Re, _, java.util.Map[String,java.util.List[Re]]] = java.util.stream.Collectors$CollectorImpl@4f83df68

JFunctionjava.util.function.Function)的别名。

具有隐式适配器的变体看起来更好(但仍需要显式类型注释):

scala> Collectors.groupingBy[Re, String]((r: Re) => r.pName)
res4: java.util.stream.Collector[Re, _, java.util.Map[String,java.util.List[Re]]] = java.util.stream.Collectors$CollectorImpl@71075444