¿Cuál es el mejor equivalente de Java para Linq? [cerrado]

17

¿Hay alguna biblioteca en Java que se acerque a proporcionar la funcionalidad de Linq?

rdasxy
fuente
1
Supongo que quiere decir "la sintaxis de LINQ" en lugar de "la funcionalidad de LINQ". Hay muchas bibliotecas que ofrecen la misma funcionalidad :-)
mikera
El equivalente de Java es muy probablemente Groovy . Sin embargo
mosquito

Respuestas:

20

Para obtener una sintaxis de consulta LINQ completa, necesitaría una actualización de las especificaciones del lenguaje y compiladores que admitan las nuevas palabras clave y la estructura de sintaxis. Esto está mucho más allá de la mayoría de los lectores aquí.

Para obtener una sintaxis de cadena de método similar a Linq en Java que se ve y funciona como lo que está en C #, necesita dos cosas que Java no admite; métodos de extensión (métodos estáticos que se pueden aplicar a una instancia como si fuera un método de instancia) y expresiones lambda (delegados anónimos). Sin embargo, esos dos pueden ser falsificados con construcciones Java existentes, si está dispuesto a incurrir en un poco de verbosidad de codificación adicional. Una cosa que encuentro particularmente sorprendente sobre Java es la capacidad de crear implementaciones de interfaz anónimas; aplicado a una interfaz con una sola función pura, que básicamente permite delegados anónimos simples, siempre que tenga una interfaz para cada firma de método que necesitará.

Entonces, el lado IEnumerable (Iterable for the Javaheads) de Linq, como una cadena de métodos, debería ser posible aproximarlo en Java; básicamente lo implementaría como una interfaz fluida que controla una mónada. Necesitaría una clase como LinqIterable, implementando Iterable, que:

  • puede convertir cualquier entrada Iterable en una instancia de LinqIterable
  • tiene métodos para el procesamiento de listas básicas, tales como filtrado, agrupación, concatenación, intersección, ordenamiento, etc. que aceptan interfaces de una sola función y producen nuevas LinqIterables, lo que permite encadenar estos métodos, con suerte de manera "perezosa".
  • tiene métodos para transformar el LinqIterable en objetos "concretos" como ToList, ToArray, ToMap, etc.

Entonces, probablemente podría definir una biblioteca "fluida" que permitiría una declaración como:

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 creación de la biblioteca real es un ejercicio que va mucho más allá del alcance de una respuesta en una sesión de preguntas y respuestas en Internet. Solo dije que era posible, no fácil.

Los árboles de expresión no son ciencia espacial, pero sería un proyecto significativo para implementar lo que .NET tiene en esta área; no solo necesita la capacidad de construir un árbol de expresión, sino que debe poder "compilar" este árbol sobre la marcha utilizando los códigos de bytes emitidos; No sé si el reflejo de Java es tan poderoso.

KeithS
fuente
2
Curiosamente, los métodos de extensión y las expresiones lambda están en Java 8. ¿Quizás LINQ está en camino?
lxs
44
Bueno, si tiene métodos de extensión y lambdas, tiene el lado "Enumerable" de .NET's Linq sin un gran esfuerzo. Todavía, como dije, requerirá un cambio en la especificación de Java para permitir las palabras clave que hacen una consulta de Linq, pero honestamente en el uso diario de Linq no he encontrado demasiadas consultas que no son tan fáciles expresado como una cadena de métodos, y el compilador prácticamente convierte la sintaxis de Linq en cadenas de métodos (existen complementos VS que pueden convertir 1: 1 entre la mayoría de las consultas y cadenas). El siguiente trampolín real serán los árboles de expresión (Queryable Linq).
KeithS
8

Ver:

Martijn Verburg
fuente
1
¿Le importaría ampliar un poco lo que tiene cada uno de estos recursos y por qué los recomienda como respuesta a la pregunta que se hace? Las "respuestas de solo enlace" no son bienvenidas en Stack Exchange
mosquito
Hmm, supongo que es un caso que esta Q ya haya sido respondida, ¿debería modificarse como un duplicado?
Martijn Verburg
1
@MartijnVerburg: no podemos marcar las preguntas como duplicados en todos los sitios. Las respuestas realmente necesitan poder estar solo.
ChrisF
Editado, espero que ahora sea un poco más útil.
Martijn Verburg
5

No. Linq requiere muchas características de lenguaje que Java no tiene

Tom Squires
fuente
44
Java tiene genéricos.
Jonas
66
@Jonas: Eso es cierto, pero si son realmente lo suficientemente fuertes como para soportar LINQ es otra cuestión.
DeadMG
2
@DeadMG aún, Java tiene genéricos.
Mahmoud Hossam
Editado para eliminar la referencia a los genéricos
Tom Squires
3

Use Scala , por las razones explicadas aquí :

use el puerto .NET de Scala. Le da acceso nativo completo a todo en .NET, que obviamente incluye LINQ.

Si no puede, puede intentar usar libs como functionjava o lambdaj , pero no se acercará realmente a LINQ.

Landei
fuente
1
Scala no incluye nada como Linq sin bibliotecas.
Jonas
1
@Jonas: ¿Entonces? Java no incluye nada como Linq con bibliotecas.
back2dos
@ back2dos: Sí, por eso tienes que responder con una biblioteca.
Jonas
1
@Jonas: la biblioteca estándar de Scala es como LINQ. O al revés: LINQ es solo un conjunto de expresiones de programación funcionales para C #. Más sobre eso aquí .
back2dos
@ back2dos: Gracias por el excelente enlace, tomé la libertad de incluirlo.
Landei
2

Agregaría guayaba a la lista de bibliotecas que pueden ayudarlo a lograr algunas de las cosas que hace LINQ.

Pero como otros han señalado, no hay equivalente en Java puro.

Otto Allmendinger
fuente
¿Le importaría explicar más sobre lo que hace y por qué lo recomienda como respuesta a la pregunta que se hace? Las "respuestas de solo enlace" no son bienvenidas en Stack Exchange
mosquito
2

Puede usar Korma , un DSL para consultas SQL escritas en Clojure.

La sintaxis es bastante clara:

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

Puede llamar a esto con bastante facilidad desde Java importando las bibliotecas Clojure relevantes y simplemente usando la interoperabilidad Clojure / Java normal.

mikera
fuente
Entonces, esto emulará Linq sobre SQL, no LINQ sobre objetos, ¿verdad?
Trabajo
@ Job: sí, está diseñado para SQL. Aunque no veo ninguna razón para que no se pueda extender / adaptar también para objetos.
mikera
2

No hay una característica nativa en Java que imite linq. Sin embargo, hay varias API que proporcionan la misma funcionalidad.

Por ejemplo, esta publicación de blog tiene un jar personalizado para replicar linq.
http://javaworldwide.blogspot.in/2012/09/linq-in-java.html

Y este es un ejemplo de uso de la API de la publicación:

Supongamos que tenemos un objeto Animal que contiene nombre e ID que se representa con una lista de animals. Si queremos obtener todos los nombres de animales que contienen 'o' de la lista animals, podemos escribir la siguiente consulta

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

Hay otras dos API a las que se hace referencia en la publicación del blog: lambdaJ y jLinq

vishnu
fuente
1
Me temo que perder tanto la comprobación de tipo estático como la comprobación de la existencia misma de un miembro de la clase es un precio un poco elevado para solicitar una llamada como where("getName", ...).
9000