2011-07-05 184 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