Как использовать scala.collection.immutable.List в коде Java
Мне нужно написать код, сравнивающий производительность Java ArrayList
с Scala List
. Мне тяжело получить Scala List
, работающий в моем Java-коде. Может ли кто-нибудь опубликовать реальный простой пример "привет мир", как создать Scala List
в java-коде (в файле .java
) и добавить к нему 100 случайных чисел?
PS: Я хорошо разбираюсь в Java, но никогда не использовал Scala.
Ответы
Ответ 1
Проще использовать коллекции Java в Scala, чем наоборот, но так как вы спросили:
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 в пути к классам:
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)
Чтобы использовать коллекцию Java из Scala, вам не нужно делать ничего особенного:
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]
Ответ 2
Используйте scala.collection.JavaConversions изнутри java.
Например, для создания вложенного класса класса 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<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;
}
Ответ 3
Какое ужасное сравнение! Я оставлю его другим, чтобы объяснить, как выполнить то, что вы хотите, но вот несколько причин, почему это даже нельзя судить:
- Scala
List
- постоянная, неизменная коллекция, ArrayList
- изменяемая коллекция;
- Это означает, что
ArrayList
должен быть скопирован перед передачей методам, которые могут его изменить, если содержимое должно быть сохранено, а в List
;
- Это также означает, что операции
ArrayList
не поддерживаются в List
;
-
List
имеет постоянный прединд, ArrayList
имеет амортизацию с постоянным временем. Оба имеют линейное время в другой операции.
-
ArrayList
имеет индексированный доступ с постоянным временем, List
имеет линейный индекс с индексом времени, который в любом случае не предназначен для использования;
-
List
следует использовать с помощью методов самооблечения, таких как foreach
, map
и filter
, которые используют замыкания, ArrayList
проходит через внешний итератор или индекс.
Итак, в основном, каждый сосать в других эффективных операциях, а сами алгоритмы, используемые с ним, не должны использоваться с другими. Давайте рассмотрим те самые критерии, которые вы предлагаете:
создать scala Список и добавить 100 случайные числа к нему
Вы не добавляете элементы в scala List
- он неизменен. Вы создаете новый List
на основе существующего List
и нового элемента. В итоге у вас будет 100 различных списков (от 1 до 100), все из которых могут быть использованы без изменения другого. Между тем, если вы добавите 100 элементов в ArrayList
, у вас будет один ArrayList
размером 100. Таким образом, независимо от разницы во времени, каждая операция делала что-то другое.
Edit
Я размещаю здесь немного другую версию кода naten, которая использует метод на List
сам, чтобы добавить элемент вместо вызова 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;
}
}
И, отвечая на ваш вопрос к нему, $colon$colon
описывает, как scala представляет метод ::
в JVM, являющийся методом, используемым для добавления элементов. Кроме того, этот метод связывается справа, а не слева, что отражает характер операции, поэтому комментарий 1::nil
вместо nil::1
.
Пустой список, Nil$.MODULE$
, ссылается вместо созданного заново, потому что он singleton - нет способа создать пустой список.
Ответ 4
Я думаю, что самый простой маршрут - начать с интерфейса Java и реализовать его в scala. Например, создайте java.util.List-реализацию вокруг списка scala в scala. Как правило:
class ScalaList[T](val ts: T*) extends java.util.List[T] {
// Add all the methods, but implement only the neccessary ones
// Add all ts
}