Jaki jest najlepszy odpowiednik Java dla Linq? [Zamknięte]

17

Czy są jakieś biblioteki w Javie, które są bliskie zapewnienia funkcjonalności Linq?

rdasxy
źródło
1
Zakładam, że masz na myśli „składnię LINQ”, a nie „funkcjonalność LINQ”. Istnieje wiele bibliotek, które zapewniają tę samą funkcjonalność :-)
mikera
Odpowiednikiem Java jest najprawdopodobniej Groovy . Jednak kosztem utraty bezpieczeństwa typu
komara

Odpowiedzi:

20

Aby uzyskać pełną składnię zapytań LINQ, potrzebna byłaby aktualizacja specyfikacji języka i kompilatorów obsługujących nowe słowa kluczowe i strukturę składni. To znacznie wykracza poza większość czytelników tutaj.

Aby uzyskać podobną do Linqa składnię łańcucha metod w Javie, która wygląda i działa jak w C #, potrzebujesz dwóch rzeczy, których Java nie obsługuje; metody rozszerzenia (metody statyczne, które można zastosować do instancji tak, jakby była to metoda instancji) oraz wyrażenia lambda (anonimowi delegaci). Te dwa elementy można jednak sfałszować za pomocą istniejących konstrukcji Java, jeśli chcesz ponieść trochę dodatkowej gadatliwości kodowania. Jedną z rzeczy, które szczególnie mnie interesują w Javie, jest możliwość tworzenia anonimowych implementacji interfejsu; zastosowane do interfejsu z pojedynczą czystą funkcją, która zasadniczo pozwala na proste anonimowe delegowanie, pod warunkiem, że masz interfejs dla każdej podpisu metody, której potrzebujesz.

Zatem strona IEnumerable (Iterable for Javaheads) Linq, jako łańcuch metod, powinna być możliwa do przybliżenia w Javie; w zasadzie zaimplementowałbyś go jako płynny interfejs kontrolujący monadę. Potrzebujesz takiej klasy, jak LinqIterableimplementacja Iterable, która:

  • może konwertować dowolne dane wejściowe Iterable na instancję LinqIterable
  • ma metody podstawowego przetwarzania list, takie jak filtrowanie, grupowanie, konkatenacja, przecięcie, porządkowanie itp., które akceptują interfejsy jednofunkcyjne i produkują nowe LinqIterables, umożliwiając tworzenie łańcuchów tych metod, miejmy nadzieję, w „leniwy” sposób.
  • ma metody przekształcania LinqIterable z powrotem w „konkretne” obiekty, takie jak ToList, ToArray, ToMap itp.

Prawdopodobnie mógłbyś zdefiniować „płynną” bibliotekę, która pozwoliłaby na stwierdzenie takie jak:

Map<String, Integer> results = Linq.FromIterable(sourceList)
                           .Where(new Predicate{public bool Op(SomeStruct in){return in.SomeString == "criteria";}})
                           .OrderBy(new Func{public String Op(SomeStruct in){return in.SomeOtherString;}})
                           .Select(new Func{public SomeOtherStruct Op(SomeStruct in){return new SomeOtherStruct(in.SomeOtherString, in.SomeInt);}})
                           .ToMap(new Func{public String Op(SomeOtherStruct in){return in.StringField;}},
                                  new Func{public Integer Op(SomeOtherStruct in){return in.IntField;}});

Stworzenie faktycznej biblioteki jest ćwiczeniem znacznie wykraczającym poza zakres odpowiedzi w internetowych pytaniach i odpowiedziach. Powiedziałem tylko, że to możliwe, a nie łatwe.

Drzewa ekspresyjne nie są nauką rakietową, ale wdrożenie tego, co .NET ma w tym obszarze, byłoby znaczącym projektem; nie tylko potrzebujesz zdolności do budowania drzewa wyrażeń, musisz także być w stanie „skompilować” to drzewo w locie za pomocą emitowanych kodów bajtowych; Nie wiem, czy odbicie Javy jest tak potężne.

KeithS
źródło
2
Zabawne metody rozszerzenia i wyrażenia lambda są w Javie 8. Być może LINQ jest już w drodze?
lxs,
4
Cóż, jeśli masz metody rozszerzeń i lambdas, masz „wyliczalną” stronę Linq .NET bez wielkiego wysiłku. Nadal będzie, jak powiedziałem, wymagać zmiany specyfikacji Java, aby zezwolić na słowa kluczowe, które tworzą zapytanie Linq, ale szczerze mówiąc, w codziennym użyciu Linq nie znalazłem zbyt wielu zapytań, które nie są tak łatwe wyrażony jako łańcuch metod, a kompilator prawie konwertuje składnię Linq na łańcuchy metod (istnieją wtyczki VS, które mogą konwertować 1: 1 między większością zapytań i łańcuchów). Następnym prawdziwym odskocznią będą drzewa ekspresji (Queryable Linq).
KeithS,
8

Widzieć:

Martijn Verburg
źródło
1
czy mógłbyś rozwinąć nieco treść każdego z tych zasobów i dlaczego polecasz je jako odpowiedź na zadane pytanie? „Tylko odpowiedzi” nie są mile widziane na Stack Exchange
gnat
Hmm, myślę, że to jest przypadek, że na to Q zostało już udzielone odpowiedzi - powinno być zmodyfikowane jako duplikat?
Martijn Verburg,
1
@MartijnVerburg - nie możemy oznaczać pytań jako duplikatów w różnych witrynach. Odpowiedzi naprawdę muszą być samodzielne.
ChrisF
Edytowane, mam nadzieję, że jest teraz trochę bardziej pomocne.
Martijn Verburg,
5

Nie. Linq wymaga wielu funkcji językowych, których Java po prostu nie ma

Tom Squires
źródło
4
Java ma generyczne.
Jonas
6
@Jonas: To prawda, ale to, czy faktycznie są wystarczająco silne, aby obsługiwać LINQ, to inna sprawa.
DeadMG
2
@DeadMG nadal, Java ma generyczne.
Mahmoud Hossam
Edytowano, aby usunąć odniesienie do ogólnych
Tom Squires
3

Użyj Scali , z powodów wyjaśnionych tutaj :

użyj portu Scala .NET. Daje ci pełny natywny dostęp do wszystkiego w .NET, który oczywiście obejmuje LINQ.

Jeśli nie możesz, możesz spróbować użyć bibliotek takich jak functionjava lub lambdaj , ale tak naprawdę nie zbliżysz się do LINQ.

Landei
źródło
1
Scala nie obejmuje niczego takiego jak Linq bez bibliotek.
Jonas
1
@Jas: Więc? Java nie zawiera niczego takiego jak Linq z bibliotekami.
back2dos 18.10.11
@ back2dos: Tak, dlatego musisz odpowiedzieć za pomocą biblioteki.
Jonas
1
@Jonas: Standardowa biblioteka Scali jest jak LINQ. Lub na odwrót: LINQ to tylko zestaw funkcjonalnych idiomów programowania dla C #. Więcej na ten temat tutaj .
back2dos 18.10.11
@ back2dos: Dzięki za świetny link, mogłem go zamieścić.
Landei
2

Dodałbym guawa do listy bibliotek, które mogą pomóc ci osiągnąć niektóre rzeczy, które robi LINQ.

Ale jak zauważyli inni, nie ma odpowiednika w czystej Javie.

Otto Allmendinger
źródło
czy mógłbyś wyjaśnić więcej na temat tego, co robi i dlaczego polecasz to jako odpowiedź na zadane pytanie? „Tylko odpowiedzi” nie są mile widziane na Stack Exchange
gnat
2

Możesz użyć Korma , DSL do zapytań SQL napisanych w Clojure.

Składnia jest dość zgrabna:

(select user
  (with address)
  (fields :firstName :lastName :address.state)
  (where {:email "[email protected]"}))

Możesz to łatwo wywołać z Javy, importując odpowiednie biblioteki Clojure i po prostu używając zwykłego interfejsu Clojure / Java.

mikera
źródło
To będzie emulować Linq na SQL, a nie LINQ na obiektach, prawda?
Job
@Job: tak, jest przeznaczony dla SQL. Chociaż nie widzę żadnego powodu, dla którego nie mógłby być rozszerzony / dostosowany również do obiektów.
mikera
2

W Javie nie ma natywnej funkcji, która naśladuje linq. Istnieje jednak kilka interfejsów API, które zapewniają tę samą funkcjonalność.

Na przykład ten post na blogu zawiera niestandardowy słoik do replikacji linq.
http://javaworldwide.blogspot.in/2012/09/linq-in-java.html

A to jest przykładowe użycie interfejsu API z postu:

Załóżmy, że mamy obiekt Animal zawierający nazwę i identyfikator, który jest reprezentowany przez listę animals. Jeśli chcemy uzyskać z listy wszystkie nazwy zwierząt, które zawierają „o” animals, możemy napisać następujące zapytanie

from(animals).where("getName", contains("o")).all();

Istnieją dwa inne interfejsy API, o których mowa w blogu: lambdaJ i jLinq

Visnu
źródło
1
Obawiam się, że utrata zarówno statycznego sprawdzania typu, jak i sprawdzania samego istnienia członka klasy jest nieco stromą ceną za wywołanie takiego jak where("getName", ...).
9000