[英]Using Java generic class with raw types in Scala
我想在我的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構造函數(我的Scala對象中T
不可用,因為只鍵入了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代碼之間的多態性?
我編寫了涉及您的問題的基本方案,但沒有這樣的問題。 如果您沒有更多的信息,那么很難說出到底出了什么問題-特別是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
}
}
如果你有在Java代碼中的任何控制,你永遠不應該使用原始類型,如Item
在List<Item>
,如果他們是可以避免的。 有關更多信息,請參見此問題的答案。
如果無法修復Java代碼,則item.getId
將返回未知類型的對象,這將導致您看到的錯誤。 當您嘗試將其視為AnyRef
時,您幾乎找到了解決方案。 事實是, AnyRef
不是 Scala中所有類型的基本類型。 Any
是。 AnyRef
是所有可以為null
類型的基本類型,但是有些類型不能為null
,例如Int
。 因此,如果您按以下方式定義itemCounts
,那么部分代碼應該可以工作:
val itemCounts = new HashMap[Any, Int]
如果您希望itemCounts
的鍵類型是特定的東西,並且您知道它是所有項目ID的超類型,則必須使用asInstanceOf
任何asInstanceOf
:
val castedItem = item.asInstanceOf[Item[String]]
val castedItem = item.asInstanceOf[Item[AnyRef]]
或ID:
val castedId = item.getId.asInstanceOf[Integer]
val castedId = item.getId.asInstanceOf[AnyRef]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.