Quel est le meilleur équivalent Java de Linq? [fermé]

17

Y a-t-il des bibliothèques en Java qui sont près de fournir les fonctionnalités de Linq?

rdasxy
la source
1
Je suppose que vous voulez dire "la syntaxe de LINQ" plutôt que "la fonctionnalité de LINQ". Il existe de nombreuses bibliothèques qui offrent les mêmes fonctionnalités :-)
mikera
L'équivalent Java est très probablement Groovy . Au détriment de la perte de sécurité du type
moucher

Réponses:

20

Pour obtenir la syntaxe de requête LINQ complète, vous auriez besoin d'une mise à jour des spécifications de langue et des compilateurs prenant en charge les nouveaux mots clés et la nouvelle structure de syntaxe. C'est bien au-delà de la plupart des lecteurs ici.

Afin d'obtenir une syntaxe de chaîne de méthodes de type Linq en Java qui ressemble et fonctionne comme ce qui est en C #, vous avez besoin de deux choses que Java ne prend pas en charge; les méthodes d'extension (méthodes statiques qui peuvent être appliquées à une instance comme s'il s'agissait d'une méthode d'instance) et les expressions lambda (délégués anonymes). Cependant, ces deux peuvent être usurpés avec des constructions Java existantes, si vous êtes prêt à encourir un peu de verbosité de codage supplémentaire. Une chose que je trouve particulièrement étonnante à propos de Java est la possibilité de créer des implémentations d'interfaces anonymes; appliqué à une interface avec une seule fonction pure, qui permet essentiellement de simples délégués anonymes, à condition que vous ayez une interface pour chaque signature de méthode dont vous aurez besoin.

Ainsi, le côté IEnumerable (Iterable pour les Javaheads) de Linq, en tant que chaîne de méthode, devrait être possible d'approximer en Java; vous l'implémenteriez essentiellement comme une interface fluide qui contrôle une monade. Vous auriez besoin d'une classe comme a LinqIterable, implémentant Iterable, qui:

  • peut convertir n'importe quelle entrée Iterable en une instance LinqIterable
  • dispose de méthodes de traitement de liste de base, telles que le filtrage, le regroupement, la concaténation, l'intersection, l'ordre, etc. qui acceptent les interfaces à fonction unique et produisent de nouveaux LinqIterables, permettant le chaînage de ces méthodes, espérons-le de manière "paresseuse".
  • a des méthodes pour transformer le LinqIterable en objets "concrets" tels que ToList, ToArray, ToMap, etc.

Ainsi, vous pourriez probablement définir une bibliothèque "fluide" qui permettrait une déclaration telle que:

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

La création de la bibliothèque proprement dite est un exercice bien au-delà de la portée d'une réponse sur un Q&A Internet. Je viens de dire que c'était possible, pas facile.

Les arbres d'expression ne sont pas sorciers, mais ce serait un projet important de mettre en œuvre ce que .NET a dans ce domaine; non seulement vous avez besoin de pouvoir construire une arborescence d'expressions, mais vous devez aussi pouvoir "compiler" cette arborescence à la volée en utilisant des bytecodes émis; Je ne sais pas si la réflexion de Java est si puissante.

KeithS
la source
2
Curieusement, les méthodes d'extension et les expressions lambda sont toutes deux en Java 8. Peut-être que LINQ est en route?
lxs
4
Eh bien, si vous avez des méthodes d'extension et des lambdas, vous avez le côté "Enumerable" de Linq .NET sans un énorme effort. Comme je l'ai dit, cela nécessitera toujours une modification de la spécification Java pour autoriser les mots clés qui font une requête Linq, mais honnêtement, dans l'utilisation quotidienne de Linq, je n'ai pas trouvé trop de requêtes qui ne sont pas aussi faciles exprimée comme une chaîne de méthodes, et le compilateur convertit à peu près la syntaxe Linq en chaînes de méthodes (il existe des plugins VS qui peuvent convertir 1: 1 entre la plupart des requêtes et des chaînes). Le prochain véritable tremplin sera les arbres d'expression (Queryable Linq).
KeithS
8

Voir:

Martijn Verburg
la source
1
Pourriez-vous développer un peu plus sur chacune de ces ressources et pourquoi recommandez-vous ces réponses pour répondre à la question posée? Les «réponses de lien uniquement» ne sont pas tout à fait les bienvenues à Stack Exchange
GNAT
Hmm, je suppose que c'est un cas que ce Q avait déjà été répondu - devrait être modifié en double?
Martijn Verburg
1
@MartijnVerburg - nous ne pouvons pas marquer les questions comme des doublons sur tous les sites. Les réponses doivent vraiment être autonomes.
ChrisF
Modifié, j'espère que c'est un peu plus utile maintenant.
Martijn Verburg
5

Non. Linq nécessite de nombreuses fonctionnalités de langage que Java vient de posséder

Tom Squires
la source
4
Java a des génériques.
Jonas
6
@ Jonas: C'est vrai, mais savoir s'ils sont réellement assez forts pour prendre en charge LINQ est une autre question.
DeadMG
2
@DeadMG toujours, Java a des génériques.
Mahmoud Hossam
Modifié pour supprimer la référence aux génériques
Tom Squires
3

Utilisez Scala , pour les raisons expliquées ici :

utilisez le port .NET de Scala. Il vous donne un accès natif complet à tout dans .NET, qui inclut évidemment LINQ.

Si vous ne le pouvez pas, vous pouvez essayer d'utiliser des bibliothèques comme functionjava ou lambdaj , mais vous ne serez pas vraiment proche de LINQ.

Landei
la source
1
Scala n'inclut rien comme Linq sans bibliothèques.
Jonas
1
@Jonas: Alors? Java n'inclut rien comme Linq avec les bibliothèques.
back2dos
@ back2dos: Oui, c'est pourquoi vous devez répondre avec une bibliothèque.
Jonas
1
@Jonas: La bibliothèque standard de Scala est comme LINQ. Ou l'inverse: LINQ n'est qu'un ensemble d'idiomes de programmation fonctionnelle pour C #. Plus à ce sujet ici .
back2dos
@ back2dos: Merci pour l'excellent lien, j'ai pris la liberté de l'inclure.
Landei
2

J'ajouterais de la goyave à la liste des bibliothèques qui peuvent vous aider à réaliser certaines des choses que LINQ fait.

Mais comme d'autres l'ont souligné, il n'y a pas d'équivalent en Java pur.

Otto Allmendinger
la source
Pourriez-vous expliquer davantage ce qu'il fait et pourquoi le recommandez-vous comme répondant à la question posée? Les «réponses de lien uniquement» ne sont pas tout à fait les bienvenues à Stack Exchange
GNAT
2

Vous pouvez utiliser Korma , une DSL pour les requêtes SQL écrites en Clojure.

La syntaxe est assez soignée:

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

Vous pouvez appeler cela assez facilement à partir de Java en important les bibliothèques Clojure pertinentes et en utilisant simplement l'interopérabilité Clojure / Java normale.

mikera
la source
Donc, cela émulera Linq sur SQL, pas LINQ sur des objets, non?
Job
@Job: oui, il est conçu pour SQL. Bien que je ne vois aucune raison de ne pas pouvoir l'étendre / l'adapter aux objets également.
mikera
2

Il n'y a pas de fonctionnalité native en java qui imite linq. Cependant, il existe plusieurs API qui offrent la même fonctionnalité.

Par exemple, ce billet de blog a un pot personnalisé pour répliquer linq.
http://javaworldwide.blogspot.in/2012/09/linq-in-java.html

Et ceci est un exemple d'utilisation de l'API de la publication:

Supposons que nous ayons un objet Animal contenant le nom et l'ID qui est représenté par une liste de animals. Si nous voulons obtenir tous les noms d'animaux qui contiennent «o» dans la liste animals, nous pouvons écrire la requête suivante

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

Il y a deux autres API référencées dans la publication du blog: lambdaJ et jLinq

vishnu
la source
1
J'ai peur que perdre à la fois la vérification de type statique et la vérification de l'existence même d'un membre de la classe soit un prix un peu élevé pour appeler un appel comme where("getName", ...).
9000