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

820

¿Qué es el equivalente de Java para LINQ?

Ahmed Atia
fuente
44
Esos parecen ser LINQ to SQL.
Habla
8
Comprueba este: github.com/nicholas22/jpropel-light, ejemplo real: new String [] {"james", "john", "john", "eddie"} .where (comienza con ("j")). ToList ().distinto();
NT_
1
PPL Java todavía utilizan múltiples declaraciones y foreach que pueden ser resueltos mediante LINQ ...
om471987
1
También para Scala con API LINQ completa: github.com/nicholas22/propelS
Scooterville
44
@craastad Como un tipo .NET ahora atrapado en el mundo de Java, siento tu dolor. Sin embargo, debe probar Scala: funciones / cierres de primera clase, para comprender (no es lo mismo que la sintaxis de consulta de LINQ, pero es útil en muchas de las mismas situaciones), un sistema de tipos unificado, inferencia de tipos, algunas soluciones convenientes para la eliminación de tipos genéricos ... todo se ejecuta en la JVM, interoperando con Java. Además de muchas otras bondades funcionales como la coincidencia de patrones, el tipo de opción, etc.
Tim Goodman

Respuestas:

808

No hay nada como LINQ para Java.

...

Editar

Ahora, con Java 8, se nos presenta la API Stream , este es un tipo similar de cosas cuando se trata de colecciones, pero no es lo mismo que Linq.

Si está buscando un ORM, como Entity Framework, puede probar Hibernate

:-)

AgileJon
fuente
99
¿hay algo en el plan? integrado en el idioma? ¿Hay un número JCP? etc etc.
Cheeso
66
Muy cierto, aunque una gran parte de lo que hace que LINQ sea tan agradable es cuán profundamente está integrado en el lenguaje y el compilador
AgileJon
11
Lo sentimos, el "muy cierto" estaba destinado a 280Z28. No sé si hay un JCP para ello. LINQ necesitaba varios cambios en el lenguaje C #, dada la velocidad a la que trabaja el JCP, no aguantaría la respiración.
AgileJon
12
Esto no es correcto. Ver: stackoverflow.com/questions/10879761/…
Scooterville
23
LINQ es una especificación, no una implementación ... Las expresiones Lambda son parte de LINQ. Todos los proyectos que intentan portar LINQ a Java son implementaciones para un escenario concreto (SQL, Objetos ...) pero no cubren el objetivo principal de LINQ: integrar la consulta del lenguaje en el código. Debido a esto, no existe una alternativa real ni una iniciativa, por ahora, que pueda considerarse como una alternativa.
sesispla
154

Hay una solución alternativa, Coollection .

Coolection no ha pretendido ser el nuevo lambda, sin embargo, estamos rodeados de viejos proyectos Java heredados donde esta lib ayudará. Es realmente simple de usar y extender, cubriendo solo las acciones más utilizadas de iteración sobre colecciones, así:

from(people).where("name", eq("Arthur")).first();
from(people).where("age", lessThan(20)).all();
from(people).where("name", not(contains("Francine"))).all();
19WAS85
fuente
77
Cadena para el nombre de la columna, lo que significa que el compilador y el autocompletado IDE no ayudarán contra los errores tipográficos y la refactorización es difícil. ¿Algún plan para cambiar eso?
Ekevoo
2
Hola ekevoo Creo que será maravilloso e intenté hacerlo alguna vez. Pero en este momento, con Java 8, Coollection es una biblioteca obsoleta. Tal vez sea útil para proyectos más antiguos ... ¿Qué te parece?
19WAS85
1
@WagnerAndrade La última confirmación es hace 5-6 años. ¿Asumo que la funcionalidad fue reemplazada en gran medida por Java 8? Además, nombre muy genial :)
Abdul
145

Las Lambdas ahora están disponibles en Java 8 en forma de JSR-335 - Expresiones de Lambda para el lenguaje de programación JavaTM

ACTUALIZACIÓN : JDK8 ahora se ha lanzado que contiene el proyecto lambda. Vale la pena agarrar una copia de Java 8 en acción actualmente MEAP.

Lea los artículos de Brian Goetz relacionados con lambdas para obtener una comprensión decente de cómo se implementan las lambdas dentro de JDK8 y al mismo tiempo obtener una comprensión de las secuencias, la iteración interna, el cortocircuito y las referencias del constructor. También consulte los JSR anteriores para obtener más ejemplos .

He escrito un blog sobre algunas de las ventajas de usar lambdas en JDK8 llamado The Power of the Arrow , también NetBeans 8 tiene un gran soporte para convertir construcciones a JDK8, que también he blogueado sobre Migrar a JDK 8 con NetBeans .

Brett Ryan
fuente
¿No estaban las lambdas programadas también para estar en Java 7? ¿Que le pasó a eso?
BlueRaja - Danny Pflughoeft
77
Oracle compró Sun (lengua en la mejilla). Java 7 estaba tardando demasiado (5 años), así que lambdas se perdió la lista corta, esto fue bastante decepcionante para las masas. Dicho esto, Oracle parece que está recogiendo la pelota y creo que estamos programados para Java el 8 de octubre del próximo año.
Brett Ryan
1
Tenga en cuenta que el estado de la Lambda se ha actualizado una vez más, lo que ahora cubre flujos, iteración interna, cortocircuito y referencias de constructor. Les aconsejo a todos que lean el nuevo documento.
Brett Ryan
66
Las expresiones lambda son una pequeña parte de LINQ.
sesispla
44
@NeWNeO, si te refieres al lenguaje de consulta en C #, entonces sí, nada como esto llegará a Java, sin embargo, en mi experiencia, los desarrolladores de C # más experimentados prefieren la sintaxis lambda sobre el lenguaje de consulta. Sin embargo, si se refiere a LINQ-to-Entities, por ejemplo, encontrará que lambdas en Java habilitará esto y más. Hay mucho más en Java 8 para habilitar esto, como los métodos de defensa .
Brett Ryan
119

Puede seleccionar los elementos de una colección (y mucho más) de una manera más legible utilizando la biblioteca lambdaj

https://code.google.com/archive/p/lambdaj/

Tiene algunas ventajas sobre la biblioteca Quaere porque no usa ninguna cadena mágica, es completamente segura y, en mi opinión, ofrece un DSL más legible.

Mario Fusco
fuente
66
Esto es bueno, pero está muy lejos de estar a punto de crear una consulta y ejecutarla nuevamente sql, xml, colección, etc.
bytebender
¿por qué podría obtener java.lang.ExceptionInInitializerError cuando uso lambdaj select en una clase personalizada en mi proyecto de Android?
topwik
1
+1 esto es realmente bueno para aquellos de nosotros que no nos importa SQL / XML y solo queremos un acceso más fácil a las colecciones.
cenizas999
101

No encontrará un equivalente de LINQ a menos que use el javacc para crear su propio equivalente.

Hasta ese día, cuando alguien encuentra una manera viable de hacerlo, hay algunas buenas alternativas, como

Lukas Eder
fuente
github.com/TrigerSoft/jaque se encuentra de esta manera y permite crear árboles de expresión. Combinado con Java 8 Lambdas, cualquier capacidad de LINQ se puede implementar con el mismo esfuerzo que en .Net.
Konstantin Triger
Vea esta respuesta para una comparación: stackoverflow.com/questions/25989449/…
Konstantin Triger
49

LINQ to Objects : JAVA 8 ha agregado la API Stream que agrega soporte para operaciones de estilo funcional en flujos de valores:

Paquete java.util.stream

Explicación de Java 8: aplicación de Lambdas a colecciones de Java

LINQ to SQL / NHibernate / etc. (consulta de base de datos) : una opción sería utilizar JINQ, que también utiliza las nuevas funciones de JAVA 8 y se lanzó el 26 de febrero de 2014 en Github: https://github.com/my2iu/Jinq

Jinq proporciona a los desarrolladores una forma fácil y natural de escribir consultas de bases de datos en Java. Puede tratar los datos de la base de datos como objetos Java normales almacenados en colecciones. Puede iterar sobre ellos y filtrarlos utilizando comandos Java normales, y todo su código se traducirá automáticamente en consultas optimizadas de la base de datos. ¡Finalmente, las consultas de estilo LINQ están disponibles para Java!

Sitio del proyecto JINQ: http://www.jinq.org/

Răzvan Flavius ​​Panda
fuente
¡No estoy seguro de por qué los lectores no prestaron atención a su respuesta a pesar de que Stream API es la más cercana a LINQ!
Rafid
3
Streams API es un chiste malo en comparación con LINQ.
Andrei Rînea
1
Lo siento hombre, no quiero ser grosero. Estaba buscando un equivalente de LINQ después de golpearme la cabeza con las API de secuencias. Solo quería decir que no es un equivalente real, eso es todo.
Andrei Rînea
1
@ AndreiRînea ¿Está buscando la funcionalidad equivalente de los proveedores de LINQ (LINQ to XML, LINQ to JSON, LINQ to NHibernate, etc.)?
Răzvan Flavius ​​Panda
2
Todo lo que necesitaba era un medio para agrupar y aprovechar al máximo una colección. Eventualmente lo logré, pero con mucho esfuerzo y demasiado código.
Andrei Rînea
29

Hay un proyecto llamado quaere .

Es un marco de Java que agrega la capacidad de consultar colecciones.

Nota: Según el autor, el proyecto ya no se mantiene.

Sadegh
fuente
2
Parece que Quaere proporciona un poco de lo que LINQ proporciona, pero la pregunta es para un 'equivalente'
AgileJon
66
Entonces, ¿es algo como LINQ, si no un equivalente directo? Eso al menos suena útil
Brian Agnew
3
@AgileJon: Si realmente quisiera decir equivalente, no lo habría preguntado. Podría haber escrito from x in xs select xy encontrado la respuesta (no).
kizzx2
18

Hay muchos equivalentes de LINQ para Java, vea aquí para una comparación.

Para un marco de estilo Quaere / LINQ seguro de tipo, considere usar Querydsl . Querydsl admite colecciones JPA / Hibernate, JDO, SQL y Java.

Soy el mantenedor de Querydsl, por lo que esta respuesta es parcial.

Timo Westkämper
fuente
66
El enlace "marcos similares" está muerto. ¿Todavía tienes una página equivalente?
Lukas Eder
¿Cuándo obtendremos un libro QueryDSL? ¿O incluso opciones de entrenamiento asequibles? Su enlace de soporte 404s.
kervin
16

puedes usar scala, es similar en sintaxis y en realidad es probablemente más poderoso que linq.

Erion
fuente
1
Esp. Scala "para las comprensiones".
Nico
10

Como en 2014, finalmente puedo decir que LINQ finalmente está allí en Java 8. Así que ya no es necesario encontrar una alternativa de LINQ.

Abhinab Kanrar
fuente
9

Ahora que Java 8 admite lambdas, es posible crear API Java que se parezcan mucho a LINQ.

Jinq es una de estas nuevas bibliotecas de estilo LINQ para Java.

Soy el desarrollador de esta biblioteca. Se basa en cinco años de investigación sobre el uso del análisis de bytecode para traducir Java a consultas de bases de datos. Al igual que D-LINQ de C # es una capa de consulta que se encuentra en la parte superior de Entity Framework, Jinq puede actuar como una capa de consulta que se encuentra en la parte superior de JPA o jOOQ. Tiene soporte para agregación, grupos y subconsultas. Incluso Erik Meijer (el creador de LINQ) ha reconocido a Jinq .

Ming-Yee Iu
fuente
8

Ver SBQL4J . Es un lenguaje de consulta seguro de tipo seguro integrado con Java. Permite escribir consultas complicadas y múltiples anidadas. Hay muchos operadores, los métodos Java pueden invocarse dentro de las consultas como constructores. Las consultas se traducen a código Java puro (no hay reflejo en tiempo de ejecución), por lo que la ejecución es muy rápida.

EDITAR: Bueno, hasta ahora SBQL4J es la ÚNICA extensión al lenguaje Java que brinda capacidades de consulta similares a LINQ. Hay algunos proyectos interesantes como Quaere y JaQue, pero son solo API, no extensiones de sintaxis / semántica con seguridad de tipo fuerte en tiempo de compilación.

Emil Wcisło
fuente
66
Es posible que desee mencionar su papel en el proyecto.
Thorbjørn Ravn Andersen
8

Implementación de Java LINQ to SQL . Proporciona integración completa de idiomas y un conjunto de características más amplio en comparación con .NET LINQ.

Konstantin Triger
fuente
2
¿Puedo usar JaQue para leer / escribir archivos XML de la misma manera que podemos hacerlo con LINQ?
Khurram Majeed
7

Intenté guava-bibliotecas de google. Tiene uno FluentIterableque creo que está cerca de LINQ. Ver también FunctionalExplained .

List<String> parts = new ArrayList<String>();  // add parts to the collection.    
FluentIterable<Integer> partsStartingA = 
    FluentIterable.from(parts).filter(new Predicate<String>() {
        @Override
        public boolean apply(final String input) {
            return input.startsWith("a");
        }
    }).transform(new Function<String, Integer>() {
        @Override
        public Integer apply(final String input) {
            return input.length();
        }
    });

Parece ser una extensa biblioteca para Java. Ciertamente no es tan sucinto como LINQ pero parece interesante.

Madhan Ganesh
fuente
7

https://code.google.com/p/joquery/

Admite diferentes posibilidades,

Dada la colección,

Collection<Dto> testList = new ArrayList<>();

de tipo,

class Dto
{
    private int id;
    private String text;

    public int getId()
    {
        return id;
    }

    public int getText()
    {
        return text;
    }
}

Filtrar

Java 7

Filter<Dto> query = CQ.<Dto>filter(testList)
    .where()
    .property("id").eq().value(1);
Collection<Dto> filtered = query.list();

Java 8

Filter<Dto> query = CQ.<Dto>filter(testList)
    .where()
    .property(Dto::getId)
    .eq().value(1);
Collection<Dto> filtered = query.list();

También,

Filter<Dto> query = CQ.<Dto>filter()
        .from(testList)
        .where()
        .property(Dto::getId).between().value(1).value(2)
        .and()
        .property(Dto::grtText).in().value(new string[]{"a","b"});

Clasificación (también disponible para Java 7)

Filter<Dto> query = CQ.<Dto>filter(testList)
        .orderBy()
        .property(Dto::getId)
        .property(Dto::getName)
    Collection<Dto> sorted = query.list();

Agrupación (también disponible para Java 7)

GroupQuery<Integer,Dto> query = CQ.<Dto,Dto>query(testList)
        .group()
        .groupBy(Dto::getId)
    Collection<Grouping<Integer,Dto>> grouped = query.list();

Se une (también disponible para Java 7)

Dado,

class LeftDto
{
    private int id;
    private String text;

    public int getId()
    {
        return id;
    }

    public int getText()
    {
        return text;
    }
}

class RightDto
{
    private int id;
    private int leftId;
    private String text;

    public int getId()
    {
        return id;
    }

    public int getLeftId()
        {
            return leftId;
        }

    public int getText()
    {
        return text;
    }
}

class JoinedDto
{
    private int leftId;
    private int rightId;
    private String text;

    public JoinedDto(int leftId,int rightId,String text)
    {
        this.leftId = leftId;
        this.rightId = rightId;
        this.text = text;
    }

    public int getLeftId()
    {
        return leftId;
    }

    public int getRightId()
        {
            return rightId;
        }

    public int getText()
    {
        return text;
    }
}

Collection<LeftDto> leftList = new ArrayList<>();

Collection<RightDto> rightList = new ArrayList<>();

Se puede unir como,

Collection<JoinedDto> results = CQ.<LeftDto, LeftDto>query().from(leftList)
                .<RightDto, JoinedDto>innerJoin(CQ.<RightDto, RightDto>query().from(rightList))
                .on(LeftFyo::getId, RightDto::getLeftId)
                .transformDirect(selection ->  new JoinedDto(selection.getLeft().getText()
                                                     , selection.getLeft().getId()
                                                     , selection.getRight().getId())
                                 )
                .list();

Expresiones

Filter<Dto> query = CQ.<Dto>filter()
    .from(testList)
    .where()
    .exec(s -> s.getId() + 1).eq().value(2);
Pelican de bajo vuelo
fuente
5

Puedes probar mi biblioteca CollectionsQuery . Permite ejecutar LINQ como consultas sobre colecciones de objetos. Tienes que pasar predicado, al igual que en LINQ. Si está utilizando java6 / 7, debe utilizar una sintaxis antigua con las interfaces:

List<String> names = Queryable.from(people)
                                    .filter(new Predicate<Person>() {
                                                public boolean filter(Person p) {
                                                    return p.age>20;
                                                }
                                            })
                                    .map   (new Converter<Person,String>() {
                                                public Integer convert(Person p) {
                                                    return p.name;
                                                }
                                            })
                                    .toList();

También puede usarlo en Java8, o en Java antiguo con RetroLambda y su complemento de gradle , entonces tendrá una nueva sintaxis elegante:

List<String> names = Queryable.from(people)
                                    .filter(p->p.age>20)
                                    .map   (p->p.name)
                                    .toList();

Si necesita ejecutar consultas de base de datos, entonces puede mirar en JINQ, como se mencionó anteriormente, pero RetroLambda no puede hacer una copia de seguridad del puerto, para usar lambdas serializadas.

Bogdan Mart
fuente
4

Solo para agregar otra alternativa: Java 6 tiene una solución para consultas de bases de datos seguras con el paquete javax.persistence.criteria .

Aunque debo decir que esto no es realmente LINQ, porque con LINQ puedes consultar cualquier IEnumerable.

metator
fuente
Sí, es una API JPA. Lejos de LINQ, pero mejor que nada. Y se puede decir que se basa libremente en la API de criterios de Hibernate. Ver: docs.jboss.org/hibernate/core/3.6/reference/en-US/html/…
Hendy Irawan
4

Hay una muy buena biblioteca que puedes usar para esto.

Ubicado aquí: https://github.com/nicholas22/jpropel-light

Sin embargo, Lambdas no estará disponible hasta Java 8, por lo que usarlo es un poco diferente y no parece tan natural.

Moox
fuente
4

Parece que el Linq del que todos hablan aquí es solo LinqToObjects. Lo que creo que solo ofrece una funcionalidad que ya se puede lograr hoy en Java, pero con una sintaxis realmente fea.

Lo que veo como el verdadero poder de Linq en .Net es que las expresiones lambda se pueden usar en un contexto que requiere un Delegado o una Expresión y luego se compilarán en la forma adecuada. Esto es lo que permite que cosas como LinqToSql (o cualquier otra cosa que no sea LinqToObjects) funcionen, y les permite tener una sintaxis idéntica a LinqToObjects.

Parece que todos los proyectos mencionados anteriormente solo ofrecen las capacidades de LinqToObjects. Lo que me hace pensar que la funcionalidad de tipo LinqToSql no está en el horizonte para Java.

MarkPflug
fuente
4

Para las colecciones funcionales básicas, Java 8 lo tiene incorporado, la mayoría de los principales lenguajes JVM no Java lo tienen incorporado (Scala, Clojure, etc.), y puede agregar libs para versiones anteriores de Java.

Para el acceso integrado de lenguaje completo a una base de datos SQL, Scala (se ejecuta en la JVM) tiene Slick

arcilla
fuente
3

Para LINQ (LINQ to Objects), Java 8 tendrá algo equivalente, vea Proyecto Lambda .

Tiene extensiones de LINQ to Objects de Enumerable como cosas . Pero para cosas LINQ más complicadas como Expression y ExpressionTree (estas son necesarias para LINQ to SQL y otros proveedores de LINQ si quieren proporcionar algo optimizado y real), todavía no hay ningún equivalente, pero tal vez lo veremos en el futuro :)

Pero no creo que haya nada como consultas declarativas en Java en el futuro.

Ebrahim Byagowi
fuente
2

No existe tal característica en Java. Al usar la otra API obtendrá esta característica. Como supongamos que tenemos un objeto animal que contiene nombre e id. Tenemos una lista de objetos con objetos animales. Ahora si queremos obtener todo el nombre del animal que contiene 'o' del objeto de la lista. podemos escribir la siguiente consulta

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

La declaración de consulta anterior enumerará los animales que contienen el alfabeto 'o' en su nombre. Más información por favor vaya al siguiente blog. http://javaworldwide.blogspot.in/2012/09/linq-in-java.html

Vishnu
fuente
2

Echa un vistazo a tiny-q . (Tenga en cuenta que actualmente no puede descargarlo).

Aquí hay un ejemplo adaptado el enlace anterior:

Primero necesitamos una recopilación de algunos datos, digamos un conjunto de cadenas

String[] strings = { "bla", "mla", "bura", "bala", "mura", "buma" };

Ahora queremos seleccionar solo las cadenas que comienzan con "b":

Query<String> stringsStartingWithB = new Query<String>(strings).where(
    new Query.Func<String, Boolean>(){
        public Boolean run(String in) {
            return in.startsWith("b");
        }
    }
);

No se copió ningún dato real ni nada por el estilo, se procesará tan pronto como comience a iterar:

for(String string : stringsStartingWithB ) {
    System.out.println(string);
}
t90
fuente
1

JaQu es el equivalente de LINQ para Java. Aunque fue desarrollado para la base de datos H2, debería funcionar para cualquier base de datos ya que utiliza JDBC.

Albahaca Musa
fuente
1

Tal vez no sea la respuesta que espera, pero si alguna parte de su código necesita un trabajo pesado en las colecciones (búsqueda, clasificación, filtrado, transformaciones, análisis), puede tomar en consideración escribir algunas clases en Clojure o Scala .

Debido a su naturaleza funcional, trabajar con colecciones es en lo que son mejores. No tengo mucha experiencia con Scala, pero con Clojure probablemente encontrarás un Linq más potente a tu alcance y, una vez compiladas, las clases que producirías se integrarían perfectamente con el resto de la base de código.

pistacho
fuente
1
Groovy o jRuby también serían candidatos viables, ya que todos tienen una naturaleza mucho más funcional.
cdeszaq
1

Un usuario anónimo mencionó otro, Diting :

Diting es una biblioteca de clases que proporciona capacidades de consulta en colecciones a través de métodos encadenables y una interfaz anónima como Linq en .NET. A diferencia de la mayoría de las otras bibliotecas de colecciones que usan métodos estáticos necesitan iterar toda la colección, Diting proporciona una clase de Enumerable central que contiene métodos encadenables diferidos para implementar la consulta en la colección o matriz.

Métodos admitidos: any, cast, contact, contiene, count, distinct, elementAt, excepto, first, firstOrDefault, groupBy, interset, join, last, lastOrDefault, ofType, orderBy, orderByDescending, reverse, select, selectMany, single, singleOrDefault, skip , skipWhile, take, takeWhile, toArray, toArrayList, union, where

Rup
fuente
1

Scala. Ahora lo leí en estrella, y lo encontré como linq pero más simple y más ilegible. pero scala puede ejecutarse en linux, ¿sí? csharp necesita mono.

GéminisAmarillo
fuente
1
Scala necesita un tiempo de ejecución de Java para ejecutarse: no necesariamente funcionará en una instalación Linux desnuda, dependiendo de los componentes que instale.
Rup
@Rup hay un JRE totalmente compatible para GNU / Linux, y Mono no es una implementación de .NET totalmente compatible .
Nombre para mostrar
@Sarge Ese no era mi punto, pero Mono ejecuta LINQ lo suficientemente bien, ¿no? Además, ahora existe el propio .Net Core de Microsoft para Linux .
Rup
(GNU /) Linux no es la única plataforma además de Windows, y JRE existe para una amplia variedad de plataformas. Mono no implementa completamente todo, por ejemplo, no hay WPF.
Nombre para mostrar
0

Estaba el lenguaje de programación Pizza (una extensión de Java) y debería echarle un vistazo. - Utiliza el concepto de "interfaces fluidas" para consultar datos de manera declarativa y, en principio, es idéntico a LINQ sin expresiones de consulta (http://en.wikipedia.org/wiki/Pizza_programming_language). Pero, por desgracia, no se persiguió, pero habría sido una forma de obtener algo similar a LINQ en Java.

Nico
fuente
1
Claro que fue perseguido, solo que no bajo el nombre de "Pizza". Los genéricos de Pizza se fusionaron con GJ, que luego se convirtió en el compilador de referencia Java 1.3 (aunque los genéricos se ocultaron detrás de una bandera hasta 1.5). Mientras tanto ... el resto de las ideas, más algunas adicionales, se convirtieron en Scala.
Kevin Wright
Gracias por esa información, por supuesto, Scala es un buen punto aquí. Pero estas habilidades no estaban integradas en el lenguaje Java. Puede usar el lenguaje Scala para implementar el código de consulta agradable y usar el binario resultante luego de Java.
Nico
También vea ONGL en commons.apache.org/proper/commons-ognl , que está en uso y aún se mantiene.
Nico