我想在我的Scala程序中使用Java库。该库包含一个泛型类,它是其他类的一部分:
package java.items;
public class Item<T extends Comparable> implements Comparable<Item> {
private T id;
...
}
public final class Itemset{
private List<Item> items = new ArrayList<Item>();
public List<Item> getItems() { return items; }
...
}
public class Sequence {
private final List<Itemset> itemsets = new ArrayList<Itemset>();
public List<Itemset> getItemsets() { return itemsets; }
...
}
在我的Scala代码中,我遍历不同的对象,需要实例化类型为[T, Int]
的散列图,以便用计数器存储ID:
import java.items._
object ConvertSequence {
def ConvertSequence (dataset: RDD[(Sequence)], sc: SparkContext) {
sc.broadcast(dataset.flatMap(r => {
val itemCounts = new HashMap[AnyRef, Int]
for (itemset <- r.getItemsets) {
for (item <- itemset.getItems) {
val i = itemCounts.getOrElse(item.getId, 0)
itemCounts.update(item.getId, i + 1)
}
}
itemCounts
}).
map(r => (r._1, (r._2, 1))).
reduceByKey((x, y) => (x._1 + y._1, x._2 + y._2)).
sortBy(r => (r._2._1, r._1))
zipWithIndex().
collect({ case (k, v) => (k._1, v)})
)
}
我不知道要传递给hashmap构造函数的哪个类型(T
不能从我的Scala对象获得,因为只键入了Item
。
我试过AnyRef
但是我在编译时遇到错误:
[ERROR] error: type mismatch;
[INFO] found : ?0
[INFO] required: AnyRef
[INFO] Note that ?0 is unbounded, which means AnyRef is not a known parent.
[INFO] Such types can participate in value classes, but instances
[INFO] cannot appear in singleton types or in reference comparisons.
[INFO] val i = itemCounts.getOrElse(item.getId, 0)
[INFO] ^
[ERROR] one error found
如何管理Java和Scala代码之间的多态?
答案 0 :(得分:0)
我编写了一个涉及您问题的基本方案,没有这样的问题。如果没有关于你的结果的更多信息,很难说出究竟是什么问题 - 特别是scala代码出现的整个对象。至少你发布的代码出现的方法标题,所以我们可以检查所有类型。但这是我写的似乎有用的东西,也许这里的东西会解决你的问题:
带有泛型的Java类:
package javaCompat;
public class Item<T> {
public final T id;
public Item(T id){
this.id = id;
}
}
使用通用Java类的Scala代码:
import javaCompat.Item
import scala.collection.mutable.HashMap
object Compat {
def main(args : Array[String]){
val items =
List("A","B","C","D","E","A","B","A","C","E","F","D").map {x => new Item(x)}
print(labelCount(items))
}
def labelCount[T](items : List[Item[T]]) : HashMap[T, Int] = {
val itemCounts = new HashMap[T, Int]()
for (item <- items) {
val i = itemCounts.getOrElse(item.id, 0)
itemCounts.update(item.id, i + 1)
}
itemCounts
}
}
答案 1 :(得分:0)
如果您对Java代码有任何控制权,那么永远不会使用原始类型,例如Item
中的List<Item>
,如果它们可以避免的话。有关详细信息,请参阅this question的答案。
如果您无法修复Java代码,那么item.getId
将返回未知类型的对象,这会导致您看到的错误。当您尝试将其视为AnyRef
时,您几乎找到了解决方案。问题是,AnyRef
不是 Scala中所有类型的基本类型。 Any
是。 AnyRef
是可以null
的所有类型的基本类型,但有些类型不能null
,例如Int
。因此,如果您按如下方式定义itemCounts
,则部分代码应该有效:
val itemCounts = new HashMap[Any, Int]
如果您希望密钥类型itemCounts
是特定的,您知道的是所有项目的超类型&#39; ids,您必须使用asInstanceOf
投射项目:
val castedItem = item.asInstanceOf[Item[String]]
val castedItem = item.asInstanceOf[Item[AnyRef]]
或ids:
val castedId = item.getId.asInstanceOf[Integer]
val castedId = item.getId.asInstanceOf[AnyRef]