英文:
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]) => {
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)
}
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)]] <and>
[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]) => {
if(l.size() != 2)
throw new IllegalArgumentException("A tuple map should contain exactly 2 elements ")
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) => 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]) => {
if(l.size() != 2)
throw new IllegalArgumentException("A tuple map should contain exactly 2 elements ")
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进行进一步阅读:
集合有许多构建新集合的方法,例如map
、filter
或++
。我们称这些方法为转换器,因为它们至少以一个集合作为接收器对象,并产生另一个集合作为它们的结果。
有两种主要实现转换器的方式。一种是严格
的,即作为转换器的结果构建了一个具有所有元素的新集合。另一种是非严格
或惰性
的,即只构建了结果集合的代理,只有在需要时才构建其元素。
英文:
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]) => {
if(l.size() != 2)
throw new IllegalArgumentException("A tuple map should contain exactly 2 elements ")
val lScala = l.asScala.toArray
(lScala(0), lScala(1))
})
In scala 2.12, Map.mapValues returns a Map
.
> scala
> def mapValues[W](f: (V) ⇒ W): Map[K, W]
>
> Transforms this map by applying a function to every retrieved value.
Scala 2.13 Map.mapValues returns a MapView
.
> scala
> def mapValues[W](f: (V) => W): MapView[K, W]
>
> 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]) => {
if(l.size() != 2)
throw new IllegalArgumentException("A tuple map should contain exactly 2 elements ")
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论