How to use scala.collection.immutable.List in a Java code
I need to write a code that compares performance of Java's ArrayList with Scala's List. 开发者_如何学PythonI am having a hard time getting the Scala List working in my Java code. Can some one post a real simple "hello world" example of how to create a Scala List in java code (in a .java file) and add say 100 random numbers to it?
PS: I am quite good at Java but have never used Scala.
Use scala.collection.JavaConversions from inside of java.
For example to create a nested scala case class that requires a scala List in its constructor:
case class CardDrawn(player: Long, card: Int)
case class CardSet(cards: List[CardDrawn])
From Java you can use asScalaBuffer(x).toList() as follows:
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;
}
It's easier to use Java collections in Scala than the other way around, but since you asked:
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;
}
}
This compiles with javac with scala-library.jar in the classpath:
javac -classpath /opt/local/share/scala-2.9/lib/scala-library.jar foo.java
You can invoke from the Scala REPL:
scala> (new foo).test
List(1)
List(2, 1)
res0: List[Any] = List(2, 1)
To use a Java collection from Scala, you don't have to do anything special:
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]
What an horrible comparison! I'll leave it to others to explain how to accomplish what you want, but here's a few reasons why this shouldn't even be tried:
- Scala's
Listis a persistent, immutable collection,ArrayListis a mutable collection;- That means
ArrayListmust be copied before passed to methods that may change it, if the content must be preserved, while no such thing is necessary withList; - It also mean that
ArrayListsupport operations not possible inList;
- That means
Listhas constant-time prepend,ArrayListhas amortized constant-time append. Both have linear time the other operation.ArrayListhas constant-time indexed access,Listhas linear time indexed access, which is not the intended mode of use anyway;Listshould be used through self-traversing methods, such asforeach,mapandfilter, which use closures,ArrayListis externally traversed through an iterator or index.
So, basically, each suck at the other's efficient operations, and the very algorithms used with one shouldn't be used with the other. Let's consider the very benchmark you propose:
create a scala List and add say 100 random numbers to it
You don't add elements to a Scala List -- it is immutable. You create a new List based on an existing List and a new element. In the end, you'll have 100 different lists (of sizes 1 to 100), all of which can be used without changing the other. Meanwhile, if you add 100 elements to an ArrayList, you'll have one ArrayList of size 100. So, whatever the time difference is, each operation did something different.
Edit
I'm posting here a slightly different version of naten's code, which uses a method on List itself to prepend an element, instead of calling a factory.
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;
}
}
And, in answer to your question to him, $colon$colon is how Scala represents the method :: in the JVM, that being the method used to prepend elements. Also, that method binds to the right instead of the left, reflecting the nature of the operation, which is why the comment is 1::nil instead of nil::1.
The empty list, Nil$.MODULE$, is referenced instead of created anew because it's a singleton -- there's no way to create an empty list.
I think the easiest route would be to start with a java interface and implement that in scala. For example create a java.util.List-implementation around the scala list in scala. Typically like this:
class ScalaList[T](val ts: T*) extends java.util.List[T] {
// Add all the methods, but implement only the neccessary ones
// Add all ts
}
加载中,请稍侯......
精彩评论