簡體   English   中英

在Scala中將Java泛型類與原始類型一起使用

[英]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
  }
}

部分解決方案(無法對ID進行排序)

如果你有在Java代碼中的任何控制,你永遠不應該使用原始類型,如ItemList<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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM