Was ist das beste Java-Äquivalent zu Linq? [geschlossen]

17

Gibt es Bibliotheken in Java, die der Funktionalität von Linq nahekommen?

rdasxy
quelle
1
Ich nehme an, Sie meinen "die Syntax von LINQ" und nicht "die Funktionalität von LINQ". Es gibt viele Bibliotheken, die die gleiche Funktionalität bieten :-)
mikera
Java-Äquivalent ist höchstwahrscheinlich Groovy . Auf Kosten des
Mücke

Antworten:

20

Um die vollständige LINQ-Abfragesyntax zu erhalten, müssen Sie die Sprachspezifikation und die Compiler aktualisieren, die die neuen Schlüsselwörter und die Syntaxstruktur unterstützen. Dies ist weit jenseits der meisten Leser hier.

Um eine Linq-ähnliche Methodenkettensyntax in Java zu erhalten, die wie C # aussieht und funktioniert, benötigen Sie zwei Dinge, die Java nicht unterstützt. Erweiterungsmethoden (statische Methoden, die wie eine Instanzmethode auf eine Instanz angewendet werden können) und Lambda-Ausdrücke (anonyme Delegaten). Diese beiden können jedoch mit vorhandenen Java-Konstrukten gefälscht werden, wenn Sie bereit sind, ein wenig zusätzliche Programmier-Ausführlichkeit in Kauf zu nehmen. Eine Sache, die ich an Java besonders verblüffend finde, ist die Möglichkeit, anonyme Schnittstellenimplementierungen zu erstellen. Wird auf eine Schnittstelle mit einer einzigen reinen Funktion angewendet, die im Grunde genommen einfache anonyme Delegaten ermöglicht, vorausgesetzt, Sie haben eine Schnittstelle für jede Methodensignatur, die Sie benötigen.

Daher sollte es möglich sein, die IEnumerable-Seite (Iterable für die Javaheads) von Linq als Methodenkette in Java zu approximieren. Sie würden es im Grunde als flüssige Schnittstelle implementieren, die eine Monade steuert. Sie benötigen eine Klasse wie eine LinqIterable, die Iterable implementiert:

  • kann jede Iterable-Eingabe in eine LinqIterable-Instanz konvertieren
  • Verfügt über Methoden für die grundlegende Listenverarbeitung, z. B. Filtern, Gruppieren, Verketten, Überschneiden, Ordnen usw., die Schnittstellen mit nur einer Funktion akzeptieren und neue LinqIterables erzeugen. Dadurch können diese Methoden hoffentlich "träge" verkettet werden.
  • verfügt über Methoden, um das LinqIterable wieder in "konkrete" Objekte wie ToList, ToArray, ToMap usw. umzuwandeln

Sie könnten also wahrscheinlich eine "fließende" Bibliothek definieren, die eine Aussage wie die folgende zulässt:

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

Die Erstellung der eigentlichen Bibliothek ist eine Übung, die weit über die Beantwortung von Fragen und Antworten im Internet hinausgeht. Ich habe nur gesagt, dass es möglich ist, nicht einfach.

Ausdrucksbäume sind keine Hexenwerkzeuge, aber es wäre ein bedeutendes Projekt, das zu implementieren, was .NET in diesem Bereich hat. Sie brauchen nicht nur die Fähigkeit, einen Ausdrucksbaum zu erstellen, sondern Sie müssen in der Lage sein, diesen Baum im laufenden Betrieb unter Verwendung der ausgegebenen Bytecodes zu "kompilieren". Ich weiß nicht, ob Javas Spiegelbild so mächtig ist.

KeithS
quelle
2
Lustigerweise sind in Java 8 sowohl Erweiterungsmethoden als auch Lambda-Ausdrücke enthalten. Vielleicht ist LINQ auf dem Weg?
lxs
4
Nun, wenn Sie Erweiterungsmethoden und Lambdas haben, haben Sie die "Enumerable" -Seite von .NETs Linq ohne großen Aufwand. Wie ich bereits sagte, muss die Java-Spezifikation noch geändert werden, um die Schlüsselwörter für eine Linq-Abfrage zuzulassen. Ehrlich gesagt, habe ich bei der täglichen Verwendung von Linq nicht allzu viele Abfragen gefunden, die nicht so einfach sind Wird als Methodenkette ausgedrückt und der Compiler konvertiert die Linq-Syntax in Methodenketten (es gibt VS-Plugins, die 1: 1 zwischen den meisten Abfragen und Ketten konvertieren können). Das nächste echte Sprungbrett werden Ausdrucksbäume (Queryable Linq) sein.
KeithS
8

Sehen:

Martijn Verburg
quelle
1
Würde es Ihnen etwas ausmachen, die einzelnen Ressourcen etwas näher zu erläutern, und warum empfehlen Sie diese zur Beantwortung der gestellten Frage? "Nur-Link-Antworten" sind bei Stack Exchange nicht ganz willkommen
gnat
Hmm, ich denke, es ist ein Fall, dass dieses Q bereits beantwortet wurde - sollte als Duplikat modifiziert werden?
Martijn Verburg
1
@MartijnVerburg - Wir können Fragen nicht als Duplikate zwischen Websites markieren. Antworten müssen wirklich in der Lage sein, alleine zu stehen.
ChrisF
Bearbeitet, hoffentlich ist es jetzt etwas hilfreicher.
Martijn Verburg
5

Nein. Linq benötigt viele Sprachfunktionen, über die Java nur verfügt

Tom Squires
quelle
4
Java hat Generika.
Jonas
6
@Jonas: Das stimmt, aber ob sie tatsächlich stark genug sind, um LINQ zu unterstützen, ist eine andere Frage.
DeadMG
2
@DeadMG Java hat immer noch Generika.
Mahmoud Hossam
Bearbeitet, um den Verweis auf Generika zu entfernen
Tom Squires
3

Verwenden Sie Scala aus folgenden Gründen :

benutze den .NET Port von Scala. Es gibt Ihnen vollen nativen Zugriff auf alles in .NET, wozu natürlich auch LINQ gehört.

Wenn Sie dies nicht können, können Sie versuchen, Bibliotheken wie functionjava oder lambdaj zu verwenden , aber Sie werden LINQ nicht wirklich nahe kommen.

Landei
quelle
1
In Scala ist so etwas wie Linq ohne Bibliotheken nicht enthalten.
Jonas
1
@Jonas: Also? In Java ist so etwas wie Linq mit Bibliotheken nicht enthalten .
back2dos
@ back2dos: Ja, deshalb musst du mit einer Bibliothek antworten.
Jonas
1
@Jonas: Die Standardbibliothek von Scala ist wie LINQ. Oder umgekehrt: LINQ ist nur ein Satz funktionaler Programmiersprachen für C #. Mehr dazu hier .
back2dos
@ back2dos: Danke für den tollen Link, ich habe mir die Freiheit genommen, ihn aufzunehmen.
Landei
2

Ich würde der Liste der Bibliotheken eine Guave hinzufügen , die Ihnen dabei helfen kann, einige der Aufgaben von LINQ zu erfüllen.

Aber wie andere betont haben, gibt es in reinem Java kein Äquivalent.

Otto Allmendinger
quelle
Würde es Ihnen etwas ausmachen, mehr darüber zu erklären, was es tut, und warum empfehlen Sie es als Antwort auf die gestellte Frage? "Nur-Link-Antworten" sind bei Stack Exchange nicht ganz willkommen
gnat
2

Sie könnten Korma verwenden , ein DSL für SQL-Abfragen, das in Clojure geschrieben wurde.

Syntax ist ziemlich ordentlich:

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

Sie können dies ziemlich einfach von Java aus aufrufen, indem Sie die entsprechenden Clojure-Bibliotheken importieren und einfach das normale Clojure / Java-Interop verwenden.

mikera
quelle
Das wird also Linq über SQL emulieren, nicht LINQ über Objekte, oder?
Job
@ Job: ja, es ist für SQL ausgelegt. Obwohl ich keinen Grund sehe, dass es nicht auch für Objekte erweitert / angepasst werden kann.
Mikera
2

In Java gibt es kein natives Feature, das Linq nachahmt. Es gibt jedoch mehrere APIs, die dieselbe Funktionalität bereitstellen.

Dieser Blog-Beitrag enthält beispielsweise eine benutzerdefinierte JAR-Datei zum Replizieren von Linq.
http://javaworldwide.blogspot.in/2012/09/linq-in-java.html

Und dies ist ein Beispiel für die Verwendung der API aus dem Beitrag:

Angenommen, wir haben ein Animal-Objekt mit Namen und ID, das mit einer Liste von dargestellt wird animals. Wenn wir alle Tiernamen, die 'o' enthalten, aus der Liste erhalten möchten animals, können wir die folgende Abfrage schreiben

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

Es gibt zwei weitere APIs, auf die im Blogeintrag verwiesen wird : lambdaJ und jLinq

vishnu
quelle
1
Ich befürchte, dass der Verlust sowohl der statischen Typprüfung als auch der Überprüfung der Existenz eines Klassenmitglieds einen etwas hohen Preis für einen Anruf darstellt where("getName", ...).
9000