如何在Java代码中使用scala.collection.immutable.List

我需要编写一个代码来比较Java的ArrayList和Scala的List 。 我很难让Scala List在我的Java代码中运行。 有人可以发布一个真正简单的“hello world”示例,说明如何在java代码中创建一个Scala List (在.java文件中)并添加100个随机数字吗?

PS:我非常擅长Java,但从未使用过Scala。

在Scala中使用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; } } 

这在类路径中使用scala-library.jar编译javac:

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

您可以从Scala REPL调用:

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

要使用Scala中的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] 

使用java内部的scala.collection.JavaConversions。

例如,要创建一个嵌套的scala案例类,在其构造函数中需要一个scala List:

 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 widgets) { List 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; } 

多么可怕的比较! 我将把它留给其他人来解释如何完成你想要的东西,但这里有几个原因甚至不应该尝试:

  1. Scala的List是一个持久的,不可变的集合, ArrayList是一个可变的集合;
    1. 这意味着在传递给可能更改它的方法之前必须复制ArrayList ,如果必须保留内容,而List不需List ;
    2. 这也意味着ArrayList支持List不可能的操作;
  2. List具有常量时间前置, ArrayList具有分摊的常量时间附加。 两者都具有线性时间的其他操作。
  3. ArrayList具有常量时间索引访问, List具有线性时间索引访问,这无论如何都不是预期的使用模式;
  4. List应该通过自行遍历方法使用,例如foreachmapfilter ,它们使用闭包, ArrayList通过迭代器或索引从外部遍历。

所以,基本上,每个人都会嘲笑对方的高效操作,并且与其中一个使用的算法不应该与另一个一起使用。 让我们考虑你提出的基准:

创建一个scala列表并添加100个随机数

您不向Scala List添加元素 – 它是不可变的。 您可以基于现有List和新元素创建新List 。 最后,您将拥有100个不同的列表(大小为1到100),所有这些列表都可以在不更改其他列表的情况下使用。 同时,如果向ArrayList添加100个元素,您将拥有一个大小为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是Scala如何在JVM中表示方法::这是用于预先添加元素的方法。 此外,该方法绑定到右侧而不是左侧,反映了操作的性质,这就是注释为1::nil而不是nil::1

空列表Nil$.MODULE$被引用而不是重新创建,因为它是一个单例 – 没有办法创建一个空列表。

我认为最简单的方法是从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 }