2011-07-05 109 views
11

我需要編寫一個代碼來比較Java的ArrayList與Scala的List的性能。我很難讓Scala List在我的Java代碼中工作。有人可以發佈一個真正簡單的「hello world」例子,說明如何在Java代碼中創建一個Scala List(在.java文件中)並添加100個隨機數字? PS:我很擅長Java,但從未使用過Scala。如何在Java代碼中使用scala.collection.immutable.List

+0

我想你可以編寫一個使用Java ArrayList編譯並執行的Scala代碼進行比較......所有這些都將在JVM上運行。我不確定是否可以在Java中導入Scala列表。但我是一個Scala n00b。可能是錯誤的。 – Nishant

+0

java.util.List的Scala等價物是collection.mutable.Buffer。 – David

+1

什麼樣的測試?什麼場景?哪些算法? Scala列表默認是不可變的,應該用於函數式編程模式。從Java使用它們是沒有意義的。你可以嘗試'ArrayBuffer',它與Scala'ArrayList'非常相似。 – paradigmatic

回答

13

它更容易使用Java集合斯卡拉比周圍的其他方式,但既然你問:

import scala.collection.immutable.*; 

public class foo { 
    public List test() { 
    List nil = Nil$.MODULE$; // the empty list 
    $colon$colon one = $colon$colon$.MODULE$.apply((Integer) 1, nil); // 1::nil 
    $colon$colon two = $colon$colon$.MODULE$.apply((Integer) 2, one); // 2::1::nil 
    System.out.println(one); 
    System.out.println(two); 
    return two; 
    } 
} 

這將編譯用javac使用Scala-library.jar在classpath :

javac -classpath /opt/local/share/scala-2.9/lib/scala-library.jar foo.java 

您可以從斯卡拉REPL調用:

scala> (new foo).test 
List(1) 
List(2, 1) 
res0: List[Any] = List(2, 1) 

要使用從斯卡拉Java集合,你沒有做什麼特別的:

scala> new java.util.ArrayList[Int] 
res1: java.util.ArrayList[Int] = [] 

scala> res1.add(1) 
res2: Boolean = true 

scala> res1 
res3: java.util.ArrayList[Int] = [1] 
+0

感謝naten,我必須堅持java。你爲java發佈的代碼,我有幾個問題。該代碼看起來有點奇怪,特別是「$冒號$冒號」是否在那裏我可以讀到它?問題2:是「一」還是「二」?我有點困惑,你能解釋一下,在你創建一個空列表後,兩行究竟是什麼意思?謝謝 – Shaunak

+0

$ colon $冒號是Scala中的:: class。 $ colon $ colon $ .MODULE $是:: companion對象。 「1」行僅僅是爲1 :: nil生成的字節碼翻譯成Java,可以寫爲::。apply(1,nil)。如果您想知道如何編譯Scala代碼,請在輸出上運行javap。 –

+0

@Shaunak。如果你想使用它們,你應該花點時間閱讀一下scala列表。請參閱第9步:http://www.artima.com/scalazine/articles/steps.html – paradigmatic

0

我認爲最簡單的方法是從一個java接口開始,並在scala中實現它。例如,圍繞scala中的scala列表創建一個java.util.List實現。通常是這樣的:

class ScalaList[T](val ts: T*) extends java.util.List[T] { 

    // Add all the methods, but implement only the neccessary ones 
    // Add all ts 

} 
+0

使用scala不適合我。因爲我在比較Java中的其他庫。尤其是因爲它的家庭工作問題和java的強制執行。 – Shaunak

12

多麼可怕的對比!我要把它留給別人來解釋如何完成你想要的,但在這裏就是爲什麼這甚至不應該嘗試了幾個方面的原因:

  1. Scala的List在持久的,不可變集合,ArrayList是可變集合;
    1. 這意味着ArrayList在傳遞給可能會改變它的方法之前必須被複制,如果內容必須保留,而List不需要這樣的事情;
    2. 這也意味着ArrayList支持操作不可能在List;
  2. List有固定時間前置,ArrayList已攤銷定時附加。其他操作都有線性時間。
  3. ArrayList具有恆定時間索引訪問,List具有線性時間索引訪問,這不是預期的使用模式;
  4. List應該通過自橫動方法中使用,諸如foreachmapfilter,它使用封閉件,ArrayList外部通過一個迭代或索引遍歷。

因此,基本上,每個人都會吮吸其他人的高效操作,而一個人使用的算法不應該與另一個人一起使用。讓我們考慮非常基準你建議:

創建斯卡拉列表和添加說100張 隨機數它

你不元素添加到斯卡拉List - 這是不可改變的。您基於現有的List和新元素創建新的List。最後,您將擁有100個不同的列表(大小爲1到100),所有這些列表都可以在不更改其他列表的情況下使用。同時,如果您將100個元素添加到ArrayList,則您將有一個大小爲100的ArrayList。因此,無論時間差異如何,每個操作都會有所不同。

編輯

我在這裏張貼的,而不是調用一個工廠略有不同版本的naten的代碼,它使用的List本身的方法前面加上一個元素。

import scala.collection.immutable.*; 

public class Foo { 
    public List test() { 
    List nil = Nil$.MODULE$; // the empty list 
    List one = nil.$colon$colon((Integer) 1); // 1::nil 
    List two = one.$colon$colon((Integer) 2); // 2::1::nil 
    System.out.println(one); 
    System.out.println(two); 
    return two; 
    } 
} 

而且,在回答你的問題問他,$colon$colon是斯卡拉如何代表了JVM的方法::,正在使用預先考慮要素方法。此外,該方法綁定到右側,而不是左側,反映了操作的性質,這就是爲什麼評論是1::nil而不是nil::1

空列表Nil$.MODULE$被引用而不是重新創建,因爲它是單例 - 沒有辦法創建空列表。

20

從java裏面使用scala.collection.JavaConversions。

例如創建,需要在其構造斯卡拉列表嵌套Scala的情況下類:

case class CardDrawn(player: Long, card: Int) 
case class CardSet(cards: List[CardDrawn]) 

從Java中,你可以使用asScalaBuffer(X).toList()如下:

import scala.collection.JavaConversions; 
import java.util.ArrayList; 
import java.util.List; 

public CardSet buildCardSet(Set<Widget> widgets) { 

    List<CardDrawn> cardObjects = new ArrayList<>(); 

    for(Widget t : widgets) { 
    CardDrawn cd = new CardDrawn(t.player, t.card); 
    cardObjects.add(cd); 
    } 

    CardSet cs = new CardSet(JavaConversions.asScalaBuffer(cardObjects).toList()); 
    return cs; 
} 
+0

這個答案似乎比其他人張貼在這裏好多了,也許是因爲它在2年後發佈。我不知道爲什麼它沒有得到更多的關注。謝謝你的偉大答案! – Maciek

+0

我也宣傳這個答案! – Mahdi