Scala 2.13错误:重载方法w具有多个备选项。

huangapple go评论88阅读模式
英文:

Scala 2.13 error: overloaded method w with alternatives

问题

I can provide a translation of the code and the error message for you:

我将一些代码从Scala 2.12迁移到2.13并且我有以下代码

def w(value: java.util.Map[String, java.util.List[String]]): ParamPair[Map[String, (String, String)]] = {
    val scalaMap = value.asScala.toMap

    val newMap = scalaMap.mapValues[(String, String)]( (l: java.util.List[String]) => {
        if(l.size() != 2)
            throw new IllegalArgumentException("A tuple map should contain exactly 2 elements")
        val lScala = l.asScala.toArray
        (lScala(0), lScala(1))
    })

    w(newMap)
}

在最后一行,我遇到了以下错误:

错误无法应用重载的方法w存在以下备选项
[ERROR]   (value: java.util.Map[String,java.util.List[String]])org.apache.spark.ml.param.ParamPair[Map[String,(String, String)]] <and>
[ERROR]   (value: Map[String,(String, String)])org.apache.spark.ml.param.ParamPair[Map[String,(String, String)]]
[ERROR](scala.collection.MapView[String,(String, String)])
[ERROR]     w(newMap)
[ERROR]     ^

你能解释一下问题是什么吗?

英文:

I migrate some code to scala 2.13 from 2.12 and I have the following code

def w(value : java.util.Map[String, java.util.List[String]]) : ParamPair[Map[String, (String, String)]] = {
    val scalaMap = value.asScala.toMap

    val newMap = scalaMap.mapValues[(String, String)]( (l : java.util.List[String]) =&gt; {
      if(l.size() != 2)
        throw new IllegalArgumentException(&quot;A tuple map should contain exactly 2 elements &quot;)
      val lScala = l.asScala.toArray
      (lScala(0), lScala(1))
    })

    w(newMap)
  }

that at the last line i get the error

 error: overloaded method w with alternatives:
[ERROR]   (value: java.util.Map[String,java.util.List[String]])org.apache.spark.ml.param.ParamPair[Map[String,(String, String)]] &lt;and&gt;
[ERROR]   (value: Map[String,(String, String)])org.apache.spark.ml.param.ParamPair[Map[String,(String, String)]]
[ERROR]  cannot be applied to (scala.collection.MapView[String,(String, String)])
[ERROR]     w(newMap)
[ERROR]     ^

can you explain what is the problem?

答案1

得分: 3

在scala 2.13中引入了一些与集合相关的重大变化。以下是scala 2.13中集合迁移指南中的内容:

有哪些重大变化?

  • collection.JavaConversions已不再使用,应改为使用scala.jdk.CollectionConverters。之前的建议是使用collection.JavaConverters,但现在已被弃用。
  • 描述 旧代码 新代码 自动迁移规则
    mapValues和filterKeys现在返回一个MapView而不是Map kvs.mapValues(f) kvs.mapValues(f).toMap RoughlyMapValues

首先,您需要替换集合转换器的导入。然后,您有以下旧代码:

   val newMap = scalaMap.mapValues[(String, String)]( (l : java.util.List[String]) =&gt; {
      if(l.size() != 2)
        throw new IllegalArgumentException(&quot;A tuple map should contain exactly 2 elements &quot;)
      val lScala = l.asScala.toArray
      (lScala(0), lScala(1))
    })

在Scala 2.12中,Map.mapValues返回一个Map

def mapValues[W](f: (V)  W): Map[K, W]

通过对每个检索到的值应用函数来转换此映射。

Scala 2.13中的Map.mapValues返回一个MapView

def mapValues[W](f: (V) =&gt; W): MapView[K, W]

通过对每个检索到的值应用函数来转换此映射。
已弃用(自版本2.13.0起)使用.view.mapValues(f)。将来的版本将包括此方法的严格版本(目前使用.view.mapValues(f).toMap)。

这意味着该方法的签名已更改,方法也已弃用。如迁移指南和方法的scaladoc中所详细描述的那样,您应该使用map.view.mapValues(transformation).toMap。在您的代码中应该类似于:

   val newMap = scalaMap.view.mapValues[(String, String)]( (l : java.util.List[String]) =&gt; {
      if(l.size() != 2)
        throw new IllegalArgumentException(&quot;A tuple map should contain exactly 2 elements &quot;)
      val lScala = l.asScala.toArray
      (lScala(0), lScala(1))
    }).toMap

最后一行(lScala(0), lScala(1))Tuple2[String,String],使newMap的类型为Map[String, (String, String)]。在下一行中,您调用了w函数,该函数期望一个java.util.Map[String, java.util.List[String]]。执行newMap.asJava将返回一个util.Map[String, (String, String)]

您可以参考Views进行进一步阅读:

集合有许多构建新集合的方法,例如mapfilter++。我们称这些方法为转换器,因为它们至少以一个集合作为接收器对象,并产生另一个集合作为它们的结果。

有两种主要实现转换器的方式。一种是严格的,即作为转换器的结果构建了一个具有所有元素的新集合。另一种是非严格惰性的,即只构建了结果集合的代理,只有在需要时才构建其元素。

英文:

There were some breaking changes for collections introduced in scala 2.13. Here you have the migration guide for collections in scala 2.13

> #### What are the breaking changes?
>
> - collection.JavaConversions. Use scala.jdk.CollectionConverters instead. Previous advice was to use collection.JavaConverters which is now deprecated
>
> | Description | Old Code | New Code | Automatic Migration Rule |
> |-------------|----------|----------|--------------------------|
> | mapValues and filterKeys now return a MapView instead of a Map| kvs.mapValues(f) | kvs.mapValues(f).toMap | RoughlyMapValues |

First you have to replace the import for the collection converters. Then, you have the following old code

   val newMap = scalaMap.mapValues[(String, String)]( (l : java.util.List[String]) =&gt; {
      if(l.size() != 2)
        throw new IllegalArgumentException(&quot;A tuple map should contain exactly 2 elements &quot;)
      val lScala = l.asScala.toArray
      (lScala(0), lScala(1))
    })

In scala 2.12, Map.mapValues returns a Map.

> scala
&gt; def mapValues[W](f: (V) ⇒ W): Map[K, W]
&gt;

> Transforms this map by applying a function to every retrieved value.

Scala 2.13 Map.mapValues returns a MapView.

> scala
&gt; def mapValues[W](f: (V) =&gt; W): MapView[K, W]
&gt;

> Transforms this map by applying a function to every retrieved value.
> Deprecated (Since version 2.13.0) Use .view.mapValues(f). A future version will include a strict version of this method (for now, .view.mapValues(f).toMap).

This means that the signature of the method have been changed and also the method is deprecated. As it is detailed in the migration guide and in the scaladoc of the method, you should use map.view.mapValues(transformation).toMap. In your code should be something like

   val newMap = scalaMap.view.mapValues[(String, String)]( (l : java.util.List[String]) =&gt; {
      if(l.size() != 2)
        throw new IllegalArgumentException(&quot;A tuple map should contain exactly 2 elements &quot;)
      val lScala = l.asScala.toArray
      (lScala(0), lScala(1))
    }).toMap

The last line (lScala(0), lScala(1)) is a Tuple2[String,String], making newMap of type Map[String, (String, String)]. In the next line you are calling w function which expects a java.util.Map[String, java.util.List[String]]. Doing newMap.asJava will return a util.Map[String, (String, String)].


You have the Views for further reading

> Collections have quite a few methods that construct new collections. Examples are map, filter or ++. We call such methods transformers because they take at least one collection as their receiver object and produce another collection as their result.
>
> There are two principal ways to implement transformers. One is strict, that is a new collection with all its elements is constructed as a result of the transformer. The other is non-strict or lazy, that is one constructs only a proxy for the result collection, and its elements get constructed only as one demands them.

huangapple
  • 本文由 发表于 2023年8月10日 10:48:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76872361.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定