Qual é o melhor equivalente em Java ao Linq? [fechadas]

17

Existem bibliotecas em Java que chegam perto de fornecer a funcionalidade do Linq?

rdasxy
fonte
1
Presumo que você queira dizer "a sintaxe do LINQ" em vez de "a funcionalidade do LINQ". Existem muitas bibliotecas que fornecem a mesma funcionalidade :-)
mikera
O equivalente em Java é provavelmente o Groovy . À custa de perder a segurança de tipos embora
mosquito

Respostas:

20

Para obter a sintaxe completa da consulta LINQ, você precisaria de uma atualização para as especificações e os compiladores de idioma que suportam as novas palavras-chave e estrutura de sintaxe. Isso está muito além da maioria dos leitores aqui.

Para obter a sintaxe da cadeia de método semelhante ao Linq em Java, que se parece e funciona como o que está em C #, você precisa de duas coisas que o Java não suporta; métodos de extensão (métodos estáticos que podem ser aplicados a uma instância como se fosse um método de instância) e expressões lambda (delegados anônimos). No entanto, esses dois podem ser falsificados com construções Java existentes, se você desejar incorrer em um pouco de detalhamento de codificação. Uma coisa que acho particularmente surpreendente sobre Java é a capacidade de criar implementações de interface anônimas; aplicado a uma interface com uma única função pura, que basicamente permite delegados anônimos simples, desde que você tenha uma interface para cada assinatura de método necessária.

Portanto, o lado IEnumerable (Iterable for the Javaheads) do Linq, como uma cadeia de métodos, deve ser possível aproximar em Java; você basicamente o implementaria como uma interface fluente que controla uma mônada. Você precisaria de uma classe como a LinqIterable, implementando Iterable, que:

  • pode converter qualquer entrada Iterável em uma instância LinqIterable
  • possui métodos para processamento básico de lista, como filtragem, agrupamento, concatenação, interseção, ordenação, etc, que aceitam interfaces de função única e produzem novos LinqIterables, permitindo o encadeamento desses métodos, esperançosamente de uma maneira "preguiçosa".
  • possui métodos para transformar o LinqIterable novamente em objetos "concretos", como ToList, ToArray, ToMap, etc.

Portanto, você provavelmente poderia definir uma biblioteca "fluente" que permitiria uma declaração 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;}});

A criação da biblioteca real é um exercício muito além do escopo de uma resposta nas perguntas e respostas na Internet. Eu apenas disse que era possível, não fácil.

As árvores de expressão não são ciência de foguetes, mas seria um projeto significativo para implementar o que o .NET possui nessa área; não é necessário apenas a capacidade de construir uma árvore de expressão, mas também a capacidade de "compilar" rapidamente a árvore usando bytecodes emitidos; Não sei se o reflexo de Java é tão poderoso.

KeithS
fonte
2
Curiosamente, métodos de extensão e expressões lambda estão ambos no Java 8. Talvez o LINQ esteja a caminho?
Lxs
4
Bem, se você tem métodos de extensão e lambdas, possui o lado "Enumerável" do Linq do .NET sem um grande esforço. Ainda será necessário, como eu disse, alterar as especificações Java para permitir as palavras-chave que fazem uma consulta no Linq, mas sinceramente no uso diário do Linq, não encontrei muitas consultas que não fossem tão facilmente expressa como uma cadeia de métodos, e o compilador praticamente converte a sintaxe Linq em cadeias de métodos (existem plugins VS que podem converter 1: 1 entre a maioria das consultas e cadeias). O próximo trampolim real serão as árvores de expressão (Queryable Linq).
21712 KeithS
8

Vejo:

Martijn Verburg
fonte
1
você se importaria em expandir um pouco o que cada um desses recursos possui e por que os recomenda como resposta à pergunta? "Respostas apenas para links" não são bem-vindas no Stack Exchange
gnat
Hmm, acho que esse caso já foi respondido - deve ser modificado como duplicado?
Martijn Verburg
1
@MartijnVerburg - não podemos marcar perguntas como duplicadas nos sites. As respostas realmente precisam poder ficar sozinhas.
ChrisF
Editado, espero que seja um pouco mais útil agora.
Martijn Verburg
5

Não. O Linq exige muitos recursos de linguagem que o Java apenas possui

Tom Squires
fonte
4
Java tem genéricos.
Jonas
6
@Jonas: Isso é verdade, mas se eles são realmente fortes o suficiente para suportar o LINQ é outra questão.
18711 DeadMG
2
@DeadMG ainda, Java tem genéricos.
Mahmoud Hossam
Editado para remover a referência a genéricos
Tom Squires
3

Use Scala , pelos motivos explicados aqui :

use a porta .NET do Scala. Dá a você acesso nativo completo a tudo no .NET, o que obviamente inclui o LINQ.

Se não puder, tente usar as bibliotecas como functionjava ou lambdaj , mas você não chegará muito perto do LINQ.

Landei
fonte
1
Scala não inclui nada como o Linq sem bibliotecas.
Jonas
1
@Jonas: Então? Java não inclui nada como o Linq com bibliotecas.
Back2dos
@ back2dos: Sim, é por isso que você precisa responder com uma biblioteca.
Jonas
1
@Jonas: a biblioteca padrão do Scala é como o LINQ. Ou o contrário: LINQ é apenas um conjunto de expressões funcionais de programação para C #. Mais sobre isso aqui .
back2dos
@ back2dos: Obrigado pelo ótimo link, tomei a liberdade de incluí-lo.
Landei
2

Eu adicionaria goiaba à lista de bibliotecas que podem ajudá-lo a alcançar algumas das coisas que o LINQ faz.

Mas, como outros já apontaram, não há equivalente em Java puro.

Otto Allmendinger
fonte
você se importaria de explicar mais sobre o que faz e por que o recomenda como resposta à pergunta? "Respostas apenas para links" não são bem-vindas no Stack Exchange
gnat
2

Você pode usar o Korma , um DSL para consultas SQL escritas no Clojure.

A sintaxe é bem organizada:

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

Você pode chamar isso facilmente do Java importando as bibliotecas relevantes do Clojure e apenas usando a interoperabilidade normal do Clojure / Java.

Mikera
fonte
Então, isso simulará o Linq sobre SQL, não o LINQ sobre objetos, certo?
Job
@ Job: sim, ele é projetado para SQL. Embora eu não veja nenhuma razão para que ele não possa ser estendido / adaptado a objetos também.
Mikera # 24/12
2

Não há um recurso nativo em java que imite o linq. No entanto, existem várias APIs que fornecem a mesma funcionalidade.

Por exemplo, esta postagem do blog possui um jar personalizado para replicar o linq.
http://javaworldwide.blogspot.in/2012/09/linq-in-java.html

E este é um exemplo de uso da API da postagem:

Suponha que tenhamos um objeto Animal contendo nome e ID que é representado com uma lista de animals. Se queremos obter todos os nomes de animais que contêm 'o' da lista animals, podemos escrever a seguinte consulta

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

Existem duas outras APIs mencionadas na postagem do blog: lambdaJ e jLinq

vishnu
fonte
1
Receio que perder tanto a verificação de tipo estático quanto a própria existência de um membro da classe seja um preço um pouco alto para pedir uma ligação where("getName", ...).
9000