Есть ли что-то вроде LINQ для Java?

Начал изучать LINQ с C#.
Особенно LINQ to Objects и LINQ to XML.
Мне очень нравятся возможности LINQ.

Я узнал, что существует что-то под названием JLINQ, реализация JavaScript.
Также (как сообщил Катберт) Scala будет иметь LINQ

Знаете ли вы, будет ли LINQ или что-то подобное частью Java 7?

Обновление: интересный пост 2008 г. - инструмент LINQ для Java


person Kb.    schedule 05.01.2010    source источник
comment
Я всегда считал LINQ уродливым и неправильным. Он выглядит обманчиво мощным, и с его помощью можно приготовить большие спагетти. Ведь ORM-решения стараются свести к минимуму использование SQL-подобных языков. Зачем их заново вводить?   -  person Bozho    schedule 06.01.2010
comment
Божо, LINQ — это не только ORM, но и, особенно в случае объектов linq2 в сочетании с лямбда-нотацией, система, позволяющая выполнять функциональное программирование на C#. Для многих это самая полезная функция LINQ, а не ORM.   -  person AlecZorab    schedule 06.01.2010
comment
@Bozho: Помимо того, что AlecZorab сказал о функциональной природе LINQ, проблема с языками, подобными SQL, не в их SQL-принадлежности сама по себе, их проблема заключалась в том, что они обычно реализовывались как встроенные языки на основе строк. Как бы то ни было, SQL-функциональность LINQ — это только вопрос синтаксиса по сравнению с операциями над множествами/реляциями; это могут быть ключевые слова map, zip, filter, project и т. д. вместо select, where, group by и т. д., а функциональность LINQ будет такой же, но не похожей на SQL-подобный язык.   -  person Rafa Castaneda    schedule 02.02.2010
comment
Проверьте это: github.com/nicholas22/jpropel-light, реальный пример: new String[] { james, john, john, eddie }.where(startsWith(j)).toList().distinct();   -  person NT_    schedule 08.10.2011
comment
У меня также есть библиотека, которую я только что опубликовал в версии 0.9 под названием Linq-A-Like. Согласно ответу г-на Собрала, это единственный ответ номер 3, использующий лямбда-выражения Java и меняющийся характер Iterable, как ставку, которую он может сделать для достижения номера 1. Вы можете получить его на центральном Maven здесь: search.maven.org/   -  person Groostav    schedule 19.04.2015


Ответы (8)


Посмотрите на Scala, мощный язык функционального программирования, но похожий на Java и работающий на платформе Java.

В Scala можно использовать практически те же конструкции кода, что и в LINQ, хотя и без специального синтаксиса обработки запросов, присутствующего в C# или VB.

ИЗМЕНИТЬ:

Вот пример возможностей запросов Scala:

// Get all StackOverflow users with more than 20,000 reputation points.
val topUsers = for{
    u <- users
    if u.reputation > 20000
} yield u;

println ("Users with more than 20,000 reputation:")
for (u <- topUsers) {
    println u.name
}
person catbert    schedule 05.01.2010
comment
@catbert: я добавил пример, чтобы продемонстрировать возможности запросов Scala. :) - person missingfaktor; 06.01.2010
comment
Будет ли этот запрос переведен в SQL (как в L2S) или он будет работать только с локальными данными? - person Niki; 09.01.2010
comment
Полный API LINQ для Scala: github.com/nicholas22/propelS - person Scooterville; 10.06.2012

Важно отметить, что LINQ — это четыре вещи:

  • Монадическое понимание
  • Интеграция с базой данных
  • SQL-подобный синтаксис
  • Манипуляции с АСТ

Люди, которые только что слышали об этом, могут думать об этом просто как об интеграции с базой данных. Люди, которые немного работали с ним, вероятно, думают о синтаксисе, подобном SQL. Те, кто действительно копается, будут знать о монадическом аспекте понимания, даже если они не знают, что это такое.

Если взять, например, Scala, у него будет монадическое понимание без остальных трех. Существует библиотека под названием ScalaQuery, которая обеспечивает интеграцию с базой данных посредством монадического понимания (внутренняя возможность сделать это это главная причина, по которой монады круты). Другой проект под названием ScalaQL, я думаю, намерен предоставить почти то же самое, но с использованием плагина компилятора для улучшения. Я не знал о работе Мигеля Гарсии, которую вы упомянули, но, увидев другие работы, которые он сделал, я в восторге от нее.

Однако для монадического понимания не требуется специальный синтаксис. Это просто делает его незагроможденным шаблоном. Так что этот аспект мгновенно доступен для языков с нужным уровнем поддержки дженериков.

Две вещи, которые Scala не делает. Во-первых, это SQL-подобный синтаксис. Ничего не поделаешь: синтаксис SQL выглядит неуместным в Scala. Я думаю, можно с уверенностью сказать, что большинство программистов на Scala предпочли бы остаться с тем, что им знакомо — так называемым пониманием.

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

Я думаю, что такая вещь была бы благом для Scala — черт возьми, для любого языка. Но, опять же, у меня есть опыт работы программистом на Форте, где возможность изменять код во время его компиляции была Богом данным правом. .Net может сделать это через LINQ, как и некоторые другие языки, такие как Ruby.

person Daniel C. Sobral    schedule 06.01.2010
comment
@Даниэль: +1 Спасибо. Интересный. Я не уверен, что .Net LINQ может выполнять манипуляции с AST. - person Kb.; 06.01.2010
comment
Манипуляция AST — это то, о чем дерево выражений. См. stackoverflow.com/questions/1430738/ для более подробного обсуждения. - person Daniel C. Sobral; 06.01.2010
comment
Scala может изменять код. Он основан на java. Вы можете использовать objectweb ASM, AspectJ, Spring или какой-нибудь пользовательский загрузчик классов. - person KitsuneYMG; 15.02.2010
comment
@kts Это не имеет значения, и, кроме того, я никогда не говорил, что Scala не может изменять код, хотя использование objectweb ASM, AspectJ или Spring не классифицируется как Scala. Пожалуйста, прочтите предпоследний абзац еще раз — способность, которую я описываю, — это не способность изменять код, который был скомпилирован, а возможность изменять код, в который он скомпилирован. - person Daniel C. Sobral; 16.02.2010

LINQ будет сложно использовать в Java из-за отсутствия замыканий. Предполагая, что Java 7 действительно действительно получает достаточно компактную поддержку замыкания и методы расширения, LINQ с точки зрения «точечной нотации» должен быть возможен, даже если он не получает эквивалента выражений запросов.

Библиотека коллекций Google (сейчас версия 1.0, но будет заменена на Guava, когда это будет готово) содержат множество необходимых методов, и я не удивлюсь, увидев 101 LINQ-подобные API-интерфейсы появляются, как только поддержка замыкания выглядит достаточно окончательной.

Однако я не вижу (на данный момент) того, что Java получает что-то вроде деревьев выражений, поэтому я подозреваю, что вы будете ограничены LINQ to Objects, если у вас нет пользовательской компиляции.

person Jon Skeet    schedule 05.01.2010
comment
@Джон Скит: Спасибо +1. И закрытие Java такое же, как технология LINQ в .Net? - person Kb.; 05.01.2010
comment
@Kb: замыкания также известны как лямбда-выражения в C #, и они являются основной функцией, поддерживающей LINQ (методы расширения - еще одна, но они менее важны). Деревья выражений лежат в основе LINQ to SQL (и других подобных вещей), но, как сказал Джон, они не ожидаются в Java 7. - person R. Martinho Fernandes; 05.01.2010
comment
Многие Java-системы манипулируют байтовым кодом при загрузке, а не AST во время компиляции, и платформа имеет множество хуков для облегчения этого. Деревья выражений — это стратегия реализации, а не необходимость. - person Pete Kirkham; 30.01.2010

Проверьте Quaere. Это LINQ-подобный DSL для Java, который вы можете включить в качестве библиотеки. Пример:

// Get all StackOverflow users with more than 20,000 reputation points.
Iterable<User> topUsers = from("u").in(entityManager.entity(User.class)).
    where(gt("u.getReputation()", 20000)).
    select("u");

System.out.println("Users with more than 20,000 reputation:");
for (User u : topUsers) {
    System.out.println(u.getName());
}

Однако обратите внимание, что в Java нет понятия, аналогичного методам расширения. Что бы ни было в Quaere, в значительной степени это то, с чем вы застряли; если вам нужно создать свои собственные специальные утилиты, они, вероятно, должны быть в отдельных классах утилит (ick).

Кроме того, поскольку в Java ‹ 7 нет собственных замыканий, вы застряли со строками для ссылки на вещи, и ваша IDE не может проанализировать их, чтобы показать вам проблемы, если вы что-то опечатаете. (Однако более умная IDE могла бы справиться с этим недостатком, если бы кто-то написал плагины самоанализа для Quaere.)

person John Feminella    schedule 05.01.2010
comment
Ужасно уродливое использование волшебных строк. Возможно, с закрытием Java 7 это может стать лучше. - person R. Martinho Fernandes; 05.01.2010
comment
Однако это небезопасно для типов. Например, если бы я неправильно написал u.getReputation(), это не было бы обнаружено во время компиляции. - person Daniel C. Sobral; 06.01.2010
comment
@Daniel: Да, отсюда и последний абзац: нельзя проанализировать их, чтобы показать вам проблемы, если вы что-то опечатали. - person John Feminella; 06.01.2010

Используя библиотеку lambdaj, вы можете найти пользователей с самой высокой репутацией следующим образом:

List<User> topUsers = 
    select(users, having(on(User.class).getReputation(), greaterThan(20000)));

У него есть некоторые преимущества по сравнению с библиотекой Quaere, потому что он не использует магическую строку, он полностью типобезопасен и, на мой взгляд, предлагает более читаемый DSL.

person Mario Fusco    schedule 10.01.2010

Вы можете попробовать редактирование, которое реализует цепные методы запроса в коллекции.

   Integer[] values = new Integer[] {0,1,2,3,4,5,6,7,8,9,10};

   Enumerable<Integer> query = new Enumerable<Integer>(values).where(new Predicate<Integer>(){

    @Override
    public boolean evaluate(Integer value) throws Exception {
        return value % 2 == 0;
    }});

   for(Integer i : query)
   {
       System.out.write(i);
       System.out.write('\n');
   }
person lately worm    schedule 10.09.2012

CQEngine или механизм запросов коллекции http://code.google.com/p/cqengine/ кажется чрезвычайно многообещающе. Хотя не пробовал. Это позволяет вам создавать индексы по коллекциям и запрашивать их. Предполагается, что очень быстро.

person Faheem Sohail    schedule 08.02.2013

Есть ли что-то столь же простое в использовании, как LINQ-2-SQL на JVM? Я хочу генерировать сущности (классы) из схемы БД с помощью какого-то инструмента и использовать их для непосредственного взаимодействия с БД. Есть ли решение без XML? Я не хочу комментировать классы. В .NET этот инструмент называется sqlmetal. Это своего рода препроцессор, который, так сказать, генерирует все классы БД.

Как только это будет сделано, я думаю, будет довольно легко использовать встроенные языковые конструкции Scala.

person Mohamed Bana    schedule 07.02.2010
comment
Querydsl поддерживает SQL в качестве серверной части. Вы можете создавать типы запросов из схемы базы данных. Если вам нужен более стандартный подход, рассмотрите возможность создания модели домена, совместимой с JPA, из вашей схемы и используйте Hibernate или какой-либо другой механизм JPA. Querydsl: source.mysema.com/display/querydsl/Querydsl - person Timo Westkämper; 16.05.2010