Какой лучший Java-эквивалент для Linq? [закрыто]

17

Существуют ли в Java какие-либо библиотеки, подходящие для обеспечения функциональности Linq?

rdasxy
источник
1
Я предполагаю, что вы имеете в виду «синтаксис LINQ», а не «функциональность LINQ». Есть много библиотек, которые предоставляют такую ​​же функциональность :-)
mikera
Java-эквивалент, скорее всего, Groovy . За счет потери безопасности типа, хотя
комарик

Ответы:

20

Чтобы получить полный синтаксис запроса LINQ, вам потребуется обновить спецификацию языка и компиляторы, поддерживающие новые ключевые слова и структуру синтаксиса. Это далеко за пределами большинства читателей здесь.

Чтобы получить Linq-подобный синтаксис метода-цепочки в Java, который выглядит и работает так же, как в C #, вам нужны две вещи, которые Java не поддерживает; методы расширения (статические методы, которые можно применять к экземпляру, как если бы это был метод экземпляра) и лямбда-выражения (анонимные делегаты). Тем не менее, эти два могут быть подделаны с помощью существующих конструкций Java, если вы хотите подвергнуться небольшому дополнительному многословию кодирования. Одна вещь, которую я нахожу особенно удивительной в Java, это возможность создавать анонимные реализации интерфейса; применяется к интерфейсу с единственной чистой функцией, которая в основном допускает простые анонимные делегаты, при условии, что у вас есть интерфейс для каждой сигнатуры метода, которая вам понадобится.

Таким образом, сторона Linq, IEnumerable (Iterable для Javaheads), как цепочка методов, должна быть приближена в Java; Вы бы в основном реализовали это как свободный интерфейс, который управляет монадой. Вам понадобится класс вроде a LinqIterable, реализующий Iterable, который:

  • может преобразовать любой вход Iterable в экземпляр LinqIterable
  • имеет методы для базовой обработки списков, такие как фильтрация, группировка, объединение, пересечение, упорядочение и т. д., которые принимают однофункциональные интерфейсы и создают новые LinqIterables, позволяющие связывать эти методы, надеюсь, «ленивым» образом.
  • имеет методы для преобразования LinqIterable обратно в «конкретные» объекты, такие как ToList, ToArray, ToMap и т. д.

Таким образом, вы, вероятно, могли бы определить «свободную» библиотеку, которая позволила бы оператор, такой как:

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

Создание настоящей библиотеки - упражнение, выходящее далеко за рамки ответа на вопросы и ответы в Интернете. Я просто сказал, что это возможно, а не просто.

Деревья выражений - это не ракетостроение, но было бы важным проектом реализовать то, что имеет .NET в этой области; вам нужна не только возможность строить дерево выражений, вы должны уметь «компилировать» это дерево на лету, используя испускаемые байт-коды; Я не знаю, является ли отражение Java настолько мощным.

Keiths
источник
2
Как ни странно, методы расширения и лямбда-выражения есть и в Java 8. Возможно, LINQ уже в пути?
LXS
4
Хорошо, если у вас есть методы расширения и лямбды, у вас есть «Enumerable» сторона Linq .NET без огромных усилий. Как я уже сказал, все равно потребуется изменение спецификации Java, чтобы разрешить ключевые слова, которые делают запрос Linq, но, честно говоря, при повседневном использовании Linq я не нашел слишком много запросов, которые не так просто выражается в виде цепочки методов, и компилятор в значительной степени преобразует синтаксис Linq в цепочки методов (существуют плагины VS, которые могут преобразовывать 1: 1 между большинством запросов и цепочек). Следующей реальной ступенькой будут деревья выражения (Queryable Linq).
KeithS
8

Видеть:

  • /programming/1217228/what-is-the-java-equivalent-for-linq - Некоторые говорят, что нет эквивалента или что вы можете использовать Lambdaj, чтобы имитировать его.
  • /programming/346721/linq-for-java-tool - есть упоминание о том, что до Java 8 вы также можете использовать коллекции Google для фальсификации и что язык Scala поддерживает его как функцию языка ( Scala - еще один популярный язык в JVM).
  • http://www.infoq.com/news/2007/09/quaere-linq - библиотека Java, которая теоретически обеспечивает функциональность LINQ (я сам не пробовал).
Мартейн Вербург
источник
1
Не могли бы вы немного рассказать о том, что есть у каждого из этих ресурсов, и почему вы рекомендуете их как ответ на заданный вопрос? «Ответы только на ссылки» не очень приветствуются на Stack Exchange
комнат
Хм, я полагаю, это тот случай, когда на этот вопрос уже был дан ответ - его следует модифицировать как дубликат?
Мартейн Вербург
1
@MartijnVerburg - мы не можем помечать вопросы как дубликаты на разных сайтах. Ответы действительно должны быть в состоянии стоять в одиночестве.
ChrisF
Отредактировано, надеюсь, теперь это немного более полезно.
Мартейн Вербург
5

Нет. Linq требует много функций языка, которые есть в Java

Том Сквайрс
источник
4
У Java действительно есть дженерики.
Джонас
6
@Jonas: Это правда, но достаточно ли они сильны, чтобы поддерживать LINQ, это другой вопрос.
DeadMG
2
@DeadMG все-таки, у Java действительно есть дженерики.
Махмуд Хоссам
Отредактировано, чтобы удалить ссылку на дженерики
Том Сквайр
3

Используйте Scala по причинам, объясненным здесь :

используйте .NET порт Scala. Это дает вам полный нативный доступ ко всему в .NET, который, очевидно, включает в себя LINQ.

Если вы не можете, вы можете попробовать использовать библиотеки libdaj , такие как functionjava или lambdaj , но вы не приблизитесь к LINQ.

Landei
источник
1
Scala не содержит ничего похожего на Linq без библиотек.
Джонас
1
@Jonas: Так? Java не включает в себя ничего подобного Linq с библиотеками.
back2dos
@ back2dos: Да, вот почему вы должны ответить с библиотекой.
Джонас
1
@Jonas: Стандартная библиотека Scala похожа на LINQ. Или наоборот: LINQ - это просто набор идиом функционального программирования для C #. Подробнее об этом здесь .
back2dos
@ back2dos: Спасибо за отличную ссылку, я позволил себе включить ее.
Landei
2

Я бы добавил гуаву в список библиотек, которые могут помочь вам достичь некоторых вещей, которые делает LINQ.

Но, как отмечали другие, в чистой Java нет эквивалента.

Отто Альмендингер
источник
Вы не могли бы объяснить больше о том, что он делает, и почему вы рекомендуете ответить на заданный вопрос? «Ответы только на ссылки» не очень приветствуются на Stack Exchange
комнат
2

Вы можете использовать Korma , DSL для SQL-запросов, написанных на Clojure.

Синтаксис довольно аккуратный:

(select user
  (with address)
  (fields :firstName :lastName :address.state)
  (where {:email "korma@sqlkorma.com"}))

Вы можете легко вызвать это из Java, импортировав соответствующие библиотеки Clojure и просто используя обычное взаимодействие Clojure / Java.

mikera
источник
Итак, это будет эмулировать Linq поверх SQL, а не LINQ поверх объектов, верно?
Работа
@Job: да, он предназначен для SQL. Хотя я не вижу причин, по которым его нельзя было бы расширить / адаптировать для объектов.
Микера
2

В Java нет встроенной функции, которая имитирует linq. Однако есть несколько API, которые предоставляют одинаковую функциональность.

Например, в этом сообщении в блоге есть специальный jar для репликации linq.
http://javaworldwide.blogspot.in/2012/09/linq-in-java.html

И это пример использования API из поста:

Предположим, у нас есть объект Animal, содержащий имя и идентификатор, который представлен списком animals. Если мы хотим получить все имена животных, которые содержат 'o' из списка animals, мы можем написать следующий запрос

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

В публикации блога упоминаются два других API: lambdaJ и jLinq

Вишну
источник
1
Я боюсь, что потерять как статическую проверку типов, так и проверку самого существования члена класса - это немного завышенная цена, чтобы вызывать подобные вызовы where("getName", ...).
9000