2011-07-05 13 views
11

Potrzebuję napisać kod, który porównuje wydajność Javy ArrayList z wersją List firmy Scala. Mam problem z uruchomieniem Scala List w moim kodzie Java. Czy ktoś może opublikować prosty przykład "Witaj świecie", jak utworzyć kod Scala List w kodzie Javy (w pliku .java) i dodać 100 liczb losowych do niego?Jak używać scala.collection.immutable.List w kodzie Java

PS: Jestem dość dobry w Javie, ale nigdy nie używałem Scala.

+0

Zgaduję, że możesz napisać kod Scala, który używa kompilacji Java ArrayList i wykonać, aby porównać ... po-wszystkie obie będą działać na JVM. Nie jestem pewien, czy możliwe jest zaimportowanie listy Scala w Javie. Ale ja jestem Scala n00b. Prawdopodobnie źle. – Nishant

+0

Scala odpowiednik java.util.List to collection.mutable.Buffer. – David

+1

Jakie testy? Jakie scenariusze? Jakie algorytmy? Listy Scala są domyślnie niezmienne i powinny być używane z funkcjonalnymi wzorami programowania. Nie ma sensu używać ich z Javy. Możesz wypróbować 'ArrayBuffer', który jest bardzo podobny do Scala' ArrayList'. – paradigmatic

Odpowiedz

13

Łatwiej jest użyć kolekcje Java w Scala niż na odwrót, ale skoro pytasz:

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; 
    } 
} 

To kompiluje z javac z scala-library.jar w ścieżce klasy :

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

można powołać się od Scala REPL:

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

Aby skorzystać z kolekcji Java z Scala, nie musisz robić nic specjalnego:

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

Dzięki Naten, muszę trzymać się Java. kod opublikowany dla java, mam kilka pytań. Kod wygląda trochę dziwnie, szczególnie "colon $ colon" jest gdzieś, gdzie mogę go przeczytać? Pytanie 2: czy są to listy "jedna" i "dwie"? jestem nieco zdezorientowany, czy możesz wyjaśnić, co dokładnie oznaczają dwie linie po utworzeniu pustej listy?dzięki – Shaunak

+0

$ colon $ colon to klasa :: w Scali. $ colon $ colon $ .MODULE $ to obiekt :: towarzysz. Linia "one" to po prostu tłumaczenie na język Java kodu bajtowego wygenerowanego dla 1 :: nil, które można zapisać ::. Apply (1, nil). Jeśli chcesz się dowiedzieć, w jaki sposób skompilowano kod Scala, uruchom javap na wyjściu. –

+0

@Shaunak. Powinieneś naprawdę spędzić trochę czasu czytając o listach scala, jeśli chcesz ich użyć. Zobacz krok 9 tutaj: http://www.artima.com/scalazine/articles/steps.html – paradigmatic

0

Myślę, że najłatwiejszą trasą byłoby rozpoczęcie z interfejsem java i wdrożenie tego w scala. Na przykład utwórz implementację java.util.List wokół listy scala w scala. Zazwyczaj za słuszne:

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

używanie scala nie jest dla mnie opcją. ponieważ porównuję niektóre inne biblioteki również w java. a zwłaszcza dlatego, że egzekwowany jest jego rodzaj problemu związanego z pracą domową i java. – Shaunak

12

Co za straszne porównanie! Zostawię go innym, aby wyjaśnić, jak osiągnąć to, co chcesz, ale tutaj jest kilka powodów, dla których nie powinno być nawet próbowałem:

  1. Scala List jest trwały, niezmienny zbiór, ArrayList jest zmienny zbiór ;
    1. Oznacza to ArrayList musi zostać skopiowany zanim przeszedł do metod, które mogą ją zmienić, jeśli zawartość musi zostać zachowany, a nie coś takiego jest konieczne ze List;
    2. Oznacza to również, że operacje wspierające nie są możliwe w List;
  2. List ma ciągły czas wstępny, ArrayList zamortyzował ciągłe dołączenie. Oba mają czas liniowy w drugiej operacji.
  3. ArrayList ma dostęp indeksowany o stałym czasie, List ma indeksowany czas dostępu liniowego, co i tak nie jest zamierzonym sposobem użycia;
  4. List należy stosować metodami siebie przesuwu, jak foreach, map i filter, które wykorzystują zamknięcia ArrayList jest zewnętrznie przepływa przez iteracyjnej lub indeks.

Zasadniczo, każdy zasysa efektywne operacje drugiego, a same algorytmy nie powinny być używane z innymi.Rozważmy bardzo benchmarku proponujecie:

tworzenia listy scala i dodać powiedzieć 100 liczb losowych do niego

Nie dodawać elementy do Scala List - jest niezmienna. Tworzysz nowy List w oparciu o istniejący List i nowy element. W końcu będziesz mieć 100 różnych list (o wielkości od 1 do 100), z których wszystkie mogą być używane bez zmiany drugiego. Tymczasem, jeśli dodasz 100 elementów do ArrayList, będziesz miał jeden ArrayList o rozmiarze 100. Tak więc, niezależnie od różnic czasu, każda operacja zrobiła coś innego.

Edit

jestem delegowania tutaj nieco inną wersję kodu naten, która wykorzystuje metodę na samym List do poprzedzić element, zamiast dzwonić do fabryki.

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; 
    } 
} 

A w odpowiedzi na pytanie do niego, $colon$colon sposób Scala reprezentuje metodę :: w JVM, który jest metoda stosowana do poprzedzić elementy. Ponadto ta metoda jest wiązana w prawo zamiast w lewo, odzwierciedlając charakter operacji, dlatego komentarz jest 1::nil zamiast nil::1.

Pusta lista, Nil$.MODULE$, jest przywoływana zamiast tworzona od nowa, ponieważ jest to singleton - nie ma możliwości utworzenia pustej listy.

20

Użyj scala.collection.JavaConversions z wnętrza java.

Na przykład, aby utworzyć zagnieżdżony scala klasę case że wymaga listy Scala w jego konstruktora:

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

z Java można wykorzystać asScalaBuffer (x) .toList() w następujący sposób:

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

Ta odpowiedź wydaje się trochę lepsza niż pozostałe tutaj zamieszczone, może dlatego, że została opublikowana 2 lata później. Nie jestem pewien, dlaczego nie przyciąga to więcej uwagi. Dziękuję za wspaniałą odpowiedź! – Maciek

+0

Ja również promuję tę odpowiedź! – Mahdi

Powiązane problemy