我有一个脚本。它在没有警告的情况下运行。
$ cat ~/tmp/so1.scala
import org.yaml.snakeyaml.Yaml
class JavaMapIteratorWrapper[K,V] (map: java.util.Map[K,V]) {
def foreach (f: Tuple2 [K, V] => Unit): Unit = {
val iter = map.entrySet.iterator
while (iter.hasNext) {
val entry = iter.next
f (entry.getKey, entry.getValue)
}
}
}
implicit def foreachJavaMap[K,V] (map: java.util.Map[K,V]): JavaMapIteratorWrapper[K,V] = new JavaMapIteratorWrapper[K,V](map)
val yaml = new Yaml;
(yaml load (io.Source.fromFile(argv(0)).mkString)) match {
case map: java.util.Map [_, _] => {
for (entry <- map) {
entry match {
case ("id", id: String) => System.out.println ("ID is " + id)
case (n: String, v: String) => System.out.println (n + " = " + v)
}
}
}
}
$ scala -unchecked -classpath jar/snakeyaml-1.7.jar ~/tmp/so1.scala eg/default.yaml
(program output as expected)
我想将循环提取到自己的函数中。所以我试试。
$ cat ~/tmp/so2.scala
import org.yaml.snakeyaml.Yaml
class JavaMapIteratorWrapper[K,V] (map: java.util.Map[K,V]) {
def foreach (f: Tuple2 [K, V] => Unit): Unit = {
val iter = map.entrySet.iterator
while (iter.hasNext) {
val entry = iter.next
f (entry.getKey, entry.getValue)
}
}
}
implicit def foreachJavaMap[K,V] (map: java.util.Map[K,V]): JavaMapIteratorWrapper[K,V] = new JavaMapIteratorWrapper[K,V](map)
val processMap = (map: java.util.Map [_, _]) => {
for (entry <- map) { // line 16
entry match {
case ("id", id: String) => System.out.println ("ID is " + id)
case (n: String, v: String) => System.out.println (n + " = " + v)
}
}
}
val yaml = new Yaml;
(yaml load (io.Source.fromFile(argv(0)).mkString)) match {
case map: java.util.Map [_, _] => processMap (map)
}
$ scala -unchecked -classpath jar/snakeyaml-1.7.jar ~/tmp/so2.scala eg/default.yaml
(fragment of so2.scala):16: error: type mismatch;
found : map.type (with underlying type java.util.Map[_, _])
required: java.util.Map[_$1,_$2] where type _$2, type _$1
for (entry <- map) {
^
one error found
!!!
discarding <script preamble>
循环在其自身的功能中意味着它需要更具体的类型。好。
我会尝试使用java.util.Map [AnyRef, AnyRef]
代替java.util.Map [_, _]
。
$ cat ~/tmp/so3.scala
import org.yaml.snakeyaml.Yaml
class JavaMapIteratorWrapper[K,V] (map: java.util.Map[K,V]) {
def foreach (f: Tuple2 [K, V] => Unit): Unit = {
val iter = map.entrySet.iterator
while (iter.hasNext) {
val entry = iter.next
f (entry.getKey, entry.getValue)
}
}
}
implicit def foreachJavaMap[K,V] (map: java.util.Map[K,V]): JavaMapIteratorWrapper[K,V] = new JavaMapIteratorWrapper[K,V](map)
val processMap = (map: java.util.Map [AnyRef, AnyRef]) => {
for (entry <- map) {
entry match {
case ("id", id: String) => System.out.println ("ID is " + id)
case (n: String, v: String) => System.out.println (n + " = " + v)
}
}
}
val yaml = new Yaml;
(yaml load (io.Source.fromFile(argv(0)).mkString)) match {
case map: java.util.Map [AnyRef, AnyRef] => processMap (map) // line 26
}
$ scala -unchecked -classpath jar/snakeyaml-1.7.jar ~/tmp/so3.scala eg/default.yaml
(fragment of so3.scala):26: warning: non variable type-argument AnyRef in type pattern is unchecked since it is eliminated by erasure
case map: java.util.Map [AnyRef, AnyRef] => processMap (map)
^
one warning found
!!!
discarding <script preamble>
(program output as expected)
现在它运行了,但它给了我一个警告。如何消除该警告?
注意:
答案 0 :(得分:3)
您可以尝试删除自定义包装器。 (2.8.1)Scala标准库已经包含一个包装器,可以在scala.collection.JavaConverters
中更具惯用地使用Java集合类型。 (注意:导入时不需要scala.
前缀
我还使processMap
成为方法而不是函数,并添加类型参数:
import collection.JavaConverters._
def processMap[K,V](map: Map[K, V]): Unit = {
for (entry <- map) {
entry match {
case ("id", id: String) => System.out.println ("ID is " + id)
case (n: String, v: String) => System.out.println (n + " = " + v)
}
}
}
val yaml = new Yaml
(yaml load (io.Source.fromFile(argv(0)).mkString)) match {
case map: java.util.Map[_, _] => processMap(map.asScala)
}
请注意倒数第二行的asScala
方法......
在处理Java / Scala互操作时,通常最好的做法是尽早从Java转换为Scala集合,并尽可能晚地转换回来。
答案 1 :(得分:0)
您必须使用Scala 2.7.X.如果您使用2.8.1,您的Map [_,_]示例工作正常。
如果需要使用2.7.X,请尝试将processMap值转换为方法: def processMap [K,V] =(map:java.util.Map [K,V])=&gt; {...} 这似乎为我编译,但请注意我使用YAML库“删除”部分。我用过:
val m1 = new java.util.HashMap[String,String]
m1.put("one", "1")
m1.put("id", "123")
m1.put("two", "2")
m1 match {
case map: java.util.Map [_, _] => processMap (map)
}