Что такое Java-эквивалент для LINQ? [закрыто]


820

Что такое Java-эквивалент для LINQ?


4
Похоже, что это LINQ to SQL.
Утром

8
Проверьте это: github.com/nicholas22/jpropel-light, реальный пример: new String [] {"james", "john", "john", "eddie"} .where (startWith ("j")). ToList () .distinct ();
NT_

1
Java ppl по-прежнему использует несколько операторов и циклов foreach, которые могут быть решены с помощью Linq ...
om471987

1
Также для Scala с полным API LINQ: github.com/nicholas22/propelS
Scooterville

4
@craastad Как парень .NET, который в основном застрял в мире Java, я чувствую твою боль. Вы должны попробовать Scala - функции / замыкания первого класса, для понимания (не то же самое, что синтаксис запросов LINQ, но полезный во многих из тех же ситуаций), унифицированная система типов, вывод типов, некоторые удобные обходные пути для универсального стирания типов ... все работает на JVM, взаимодействует с Java. Плюс куча других функциональных достоинств, таких как сопоставление с образцом, тип опции и т. Д.
Тим Гудман,

Ответы:


808

Нет ничего похожего на LINQ для Java.

...

редактировать

Теперь с Java 8 мы познакомились с Stream API , это похоже на то, что происходит с коллекциями, но это не совсем то же самое, что Linq.

Если вы ищете ORM, например Entity Framework, вы можете попробовать Hibernate

:-)


9
есть ли что-то в плане? интегрированы в язык? Это номер JCP? и т. д.
Cheeso

6
Совершенно верно, хотя большая часть того, что делает LINQ sooo приятным, заключается в том, насколько глубоко он интегрирован в язык и компилятор
AgileJon

11
Извините, «очень верно» предназначалось для 280Z28. Я не знаю, есть ли для этого JCP. Для LINQ потребовалось несколько изменений в языке C #, учитывая скорость работы JCP, я не мог задержать дыхание.
AgileJon

12
Это не правильно. См .: stackoverflow.com/questions/10879761/…
Scooterville

23
LINQ - это спецификация, а не реализация ... Лямбда-выражения являются частью LINQ. Все проекты, пытающиеся портировать LINQ на Java, являются реализациями для конкретного сценария (SQL, Objects ...), но не охватывают основную цель LINQ: интегрировать языковой запрос в код. В связи с этим на данный момент не существует реальной альтернативы или инициативы, которую можно рассматривать как альтернативу.
sesispla

154

Существует альтернативное решение, Coollection .

Coolection не претендует на звание новой лямбды, однако мы окружены старыми унаследованными Java-проектами, в которых эта библиотека поможет. Его действительно просто использовать и расширять, охватывая только наиболее часто используемые действия итерации над коллекциями, например:

from(people).where("name", eq("Arthur")).first();
from(people).where("age", lessThan(20)).all();
from(people).where("name", not(contains("Francine"))).all();

7
Строка для имени столбца, что означает, что автозаполнение компилятора и IDE не поможет против опечаток, и рефакторинг сложен. Есть ли планы изменить это?
Ekevoo

2
Привет, Экево. Я думаю, что это будет круто, и я попытался сделать это когда-нибудь. Но в этот момент, с Java 8, Coollection устарела. Может быть, это полезно для старых проектов ... Как вы думаете?
19WAS85

1
@WagnerAndrade Последний коммит 5-6 лет назад. Я предполагаю, что функциональность была в значительной степени заменена Java 8? Кроме того, очень крутое имя :)
Абдул

145

Лямбды теперь доступны в Java 8 в форме JSR-335 - Лямбда-выражения для языка программирования JavaTM

ОБНОВЛЕНИЕ : JDK8 теперь выпущен, который содержит лямбда-проект. Стоит взять копию Java 8 в действии, в настоящее время все еще MEAP.

Прочитайте статьи Брайана Гетца, относящиеся к лямбдам, для приличного понимания того, как лямбды реализованы в JDK8, а также для понимания потоков, внутренней итерации, коротких замыканий и ссылок на конструкторы. Также ознакомьтесь с JSR выше, чтобы получить дополнительные примеры ,

Я написал блог о преимуществах использования лямбда-выражений в JDK8 под названием «Сила стрелки» , а также в NetBeans 8 есть отличная поддержка для преобразования конструкций в JDK8, о котором я также писал в блоге о переходе на JDK 8 с NetBeans .


Разве лямбды также не были запланированы на Java 7? Что случилось с этим?
BlueRaja - Дэнни Пфлугхофт

7
Оракул купил Sun (язык в щеке). Java 7 занимал слишком много времени (5 лет), поэтому лямбды не попали в шорт-лист, это разочаровало массы. Это говорит о том, что Oracle выглядит так, словно забирает мяч, и я думаю, что у нас запланирована Java 8 октября следующего года.
Бретт Райан

1
Обратите внимание, что состояние Lambda было обновлено еще раз, и теперь оно охватывает потоки, внутренние итерации, короткие замыкания и ссылки на конструкторы. Советую всем прочитать новый документ.
Бретт Райан

6
Лямбда-выражения - небольшая часть LINQ.
sesispla

4
@NeWNeO, если вы ссылаетесь на язык запросов в C #, то да, ничего подобного в Java не происходит, однако, по моему опыту, большинство опытных разработчиков C # предпочитают лямбда-синтаксис языку запросов. Однако если вы ссылаетесь, например, на LINQ-to-Entities, вы обнаружите, что лямбда-выражения в java будут включать это и многое другое. В Java 8 появилось гораздо больше возможностей, таких как методы защитника .
Бретт Райан

119

Вы можете выбрать элементы в коллекции (и многое другое) более читабельным способом, используя библиотеку lambdaj

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

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


6
Это хорошо, но это далеко от того, чтобы собирать запрос и выполнять его снова sql, xml, collection и т. Д.
bytebender

почему я могу получить java.lang.ExceptionInInitializerError при использовании lambdaj select для пользовательского класса в моем проекте Android?
topwik

1
+1 это действительно хорошо для тех из нас, кто не заботится о SQL / XML и хочет только более легкий доступ к коллекциям.
ashes999

101

Вы не найдете эквивалент LINQ, если не используете javacc для создания собственного эквивалента.

До того дня, когда кто-то найдет жизнеспособный способ сделать это, есть несколько хороших альтернатив, таких как


github.com/TrigerSoft/jaque нашел этот путь и позволяет создавать деревья выражений. В сочетании с Java 8 Lambdas любая емкость LINQ может быть реализована с теми же усилиями, что и в .Net.
Константин Тригер

Посмотрите этот ответ для сравнения: stackoverflow.com/questions/25989449/…
Константин Тригер

49

LINQ to Objects - JAVA 8 добавил Stream API, который добавляет поддержку операций функционального стиля над потоками значений:

Пакет java.util.stream

Объяснение Java 8: применение лямбд к коллекциям Java

LINQ to SQL / NHibernate / и т. Д. (запросы к базе данных). Одним из вариантов будет использование JINQ, который также использует новые функции JAVA 8 и был выпущен 26 февраля 2014 года на Github: https://github.com/my2iu/Jinq

Jinq предоставляет разработчикам простой и естественный способ написания запросов к базе данных на Java. Вы можете обрабатывать данные базы данных как обычные объекты Java, хранящиеся в коллекциях. Вы можете перебирать их и фильтровать, используя обычные команды Java, и весь ваш код будет автоматически преобразован в оптимизированные запросы к базе данных. Наконец, запросы в стиле LINQ доступны для Java!

Сайт проекта JINQ: http://www.jinq.org/


Не знаю, почему читатели не обратили внимания на ваш ответ, хотя Stream API ближе всего к LINQ!
Рафид

3
Streams API - плохая шутка по сравнению с LINQ.
Андрей Ринея

1
Извини, не хочу быть грубым. Я искал эквивалент LINQ после того, как отогнал голову с помощью Streams API. Я просто хотел сказать, что это не настоящий эквивалент, вот и все.
Андрей Ринея

1
@ AndreiRînea Ищете ли вы поставщиков LINQ (LINQ to XML, LINQ to JSON, LINQ to NHibernate и т. Д.) С аналогичной функциональностью?
Разван Флавиус Панда

2
Все, что мне было нужно, - это средства для группировки и максимизации коллекции. Я в конечном итоге преуспел, но с большими усилиями и большим количеством кода.
Андрей Ринея

29

Есть проект под названием quaere .

Это среда Java, которая добавляет возможность запрашивать коллекции.

Примечание: по словам автора, проект больше не поддерживается.


2
Quaere выглядит так, как будто предоставляет немного того, что предоставляет LINQ, но вопрос для «эквивалента»
AgileJon

6
Так что это что-то вроде LINQ, если не прямой эквивалент? По крайней мере, это звучит полезно
Брайан Агнью

3
@AgileJon: Если бы он действительно имел в виду эквивалент, он бы не спросил. Он мог бы напечатать from x in xs select xи узнать ответ (нет).
kizzx2

18

Есть много эквивалентов LINQ для Java, см. Здесь для сравнения.

Для безопасной среды стиля Quaere / LINQ рассмотрите возможность использования Querydsl . Querydsl поддерживает коллекции JPA / Hibernate, JDO, SQL и Java.

Я поддерживаю Querydsl, поэтому этот ответ предвзят.


6
Ссылка "подобные рамки" не работает. У вас все еще есть эквивалентная страница?
Лукас Эдер

Когда мы получим книгу QueryDSL? Или даже доступные варианты обучения? Ваша ссылка поддержки 404s.
Кервин

16

Вы можете использовать scala, он похож по синтаксису, и на самом деле он, вероятно, более мощный, чем linq.


1
Особенно Скала "для понимания".
Нико

10

Как и в 2014 году, я могу наконец сказать, что LINQ наконец-то появился в java 8. Так что больше не нужно искать альтернативу LINQ.


9

Теперь, когда Java 8 поддерживает лямбда-выражения, можно создавать API-интерфейсы Java, которые очень похожи на LINQ.

Jinq - одна из этих новых библиотек в стиле LINQ для Java.

Я разработчик этой библиотеки. Он основан на пятилетнем исследовании использования анализа байт-кода для перевода Java в запросы к базе данных. Подобно тому, как D-LINQ в C # является слоем запросов, который находится поверх Entity Framework, Jinq может выступать в качестве слоя запросов, расположенного поверх JPA или jOOQ. Он поддерживает агрегацию, группы и подзапросы. Даже Эрик Мейер (создатель LINQ) признал Jinq .


8

Смотрите SBQL4J . Это безопасный по типу язык строгих запросов, интегрированный с Java. Позволяет писать сложные и многократно вложенные запросы. Операторов очень много, внутри запросов можно вызывать методы Java в качестве конструкторов. Запросы транслируются в чистый Java-код (нет отражения во время выполнения), поэтому выполнение выполняется очень быстро.

РЕДАКТИРОВАТЬ: Ну, до сих пор SBQL4J это единственное расширение языка Java, который предоставляет возможности запросов, аналогичные LINQ. Есть несколько интересных проектов, таких как Quaere и JaQue, но они являются только API, а не расширением синтаксиса / семантики с высокой степенью безопасности типов во время компиляции.


6
Вы можете упомянуть свою роль в проекте.
Турбьёрн Равн Андерсен


7

Я пробовал guava-библиотеки от Google. У него есть то, FluentIterableчто я думаю, близко к LINQ. Также см. 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();
        }
    });

Кажется, обширная библиотека для Java. Конечно, не такой лаконичный, как LINQ, но выглядит интересно.


7

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

Поддерживает разные возможности,

Данная коллекция,

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

типа,

class Dto
{
    private int id;
    private String text;

    public int getId()
    {
        return id;
    }

    public int getText()
    {
        return text;
    }
}

Фильтр

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

Также,

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

Сортировка (также доступна для Java 7)

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

Группировка (также доступна для Java 7)

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

Объединения (также доступно для Java 7)

Данный,

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

Может быть присоединен как,

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

Выражения

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

5

Вы можете попробовать мою библиотеку CollectionsQuery . Это позволяет запускать LINQ-подобные запросы над коллекциями объектов. Вы должны передать предикат, как в LINQ. Если вы используете java6 / 7, то вы должны использовать старый синтаксис с интерфейсами:

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

Вы также можете использовать его в Java8 или в старой java с RetroLambda и его плагином gradle , тогда у вас будет новый причудливый синтаксис:

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

Если вам нужно выполнить запросы к БД, вы можете посмотреть на JINQ, как упомянуто выше, но это не может быть перенесено ретроспективно с помощью RetroLambda, используйте сериализованные лямбды.



4

Просто чтобы добавить еще одну альтернативу: Java 6 действительно имеет решение для безопасных типов запросов к базе данных, используя пакет javax.persistence.criteria .

Хотя я должен сказать, что это не совсем LINQ, потому что с LINQ вы можете запросить любой IEnumerable.


Да, это JPA API. Далеко от LINQ, но лучше, чем ничего. И можно сказать, что он слабо основан на Hibernate Criteria API. См .: docs.jboss.org/hibernate/core/3.6/reference/en-US/html/…
Хенди Ираван

4

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

Расположенный здесь: https://github.com/nicholas22/jpropel-light

Хотя лямбды не будут доступны до Java 8, поэтому их использование немного отличается и не кажется таким естественным.


4

Похоже, что Linq, о котором все здесь говорят, это просто LinqToObjects. Который, я считаю, предлагает только функциональность, которая уже может быть реализована сегодня в Java, но с действительно уродливым синтаксисом.

Я вижу реальную силу Linq в .Net в том, что лямбда-выражения можно использовать в контексте, требующем либо делегата, либо выражения, и затем они будут скомпилированы в соответствующую форму. Это то, что позволяет работать таким вещам, как LinqToSql (или что-то кроме LinqToObjects), и позволяет им иметь синтаксис, идентичный LinqToObjects.

Похоже, что все проекты, упомянутые выше, предлагают только возможности LinqToObjects. Что заставляет меня задуматься о том, что функциональность типа LinqToSql не стоит на пороге Java.


4

Для базовых функциональных коллекций он встроен в Java 8, в большинство основных языков JVM, не относящихся к Java, он встроен (Scala, Clojure и т. Д.), И вы можете получить дополнительные библиотеки для более ранних версий Java.

Для полного языкового интегрированного доступа к базе данных SQL в Scala (работает на JVM) есть Slick


3

Для LINQ (LINQ to Objects) Java 8 будет иметь нечто эквивалентное, см. Project Lambda .

Он имеет расширения LINQ to Objects Enumerable, такие как вещи . Но для более сложных вещей LINQ, таких как Expression и ExpressionTree (они необходимы для LINQ to SQL и других провайдеров LINQ, если они хотят предоставить что-то оптимизированное и реальное), эквивалента пока нет, но, возможно, мы увидим это в будущем :)

Но я не думаю, что в будущем будет что-то вроде декларативных запросов на Java.


2

Там нет такой функции в Java. Используя другой API, вы получите эту функцию. Например, предположим, что у нас есть животный объект, содержащий имя и идентификатор. У нас есть список объектов с животными. Теперь, если мы хотим получить имя животного, которое содержит 'o', из объекта списка. мы можем написать следующий запрос

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

Выше заявления Query будет список животных, которые содержат алфавит «о» в их названии. Более подробную информацию можно найти в следующем блоге. http://javaworldwide.blogspot.in/2012/09/linq-in-java.html


2

Проверьте крошечный вопрос . (Обратите внимание, что в настоящее время вы не можете скачать его.)

Вот пример адаптированной вышеуказанной ссылки:

Сначала нам нужен набор некоторых данных, скажем, набор строк

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

Теперь мы хотим выбрать только те строки, которые начинаются с «b»:

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

Фактические данные не были скопированы или что-то подобное, они будут обработаны, как только вы начнете выполнять итерации:

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

1

JaQu - это эквивалент LINQ для Java. Хотя он был разработан для базы данных H2, он должен работать для любой базы данных, поскольку он использует JDBC.


1

Возможно, это не тот ответ, на который вы надеетесь, но если какая-то часть вашего кода требует большой работы над коллекциями (поиск, сортировка, фильтрация, преобразования, анализ), вы можете подумать о том, чтобы написать некоторые классы в Clojure или Scala .

Из-за их функционального характера работа с коллекциями - это то, в чем они лучше всего работают. У меня нет большого опыта работы со Scala, но с Clojure вы, вероятно, найдете более мощный Linq у себя под рукой, и после компиляции классы, которые вы создадите, будут легко интегрироваться с остальной частью кода.


1
Groovy или jRuby также будут подходящими кандидатами, поскольку все они имеют гораздо более функциональный характер.
cdeszaq

1

Анонимный пользователь упомянул еще один, Дитинг :

Diting - это библиотека классов, которая предоставляет возможности запросов к коллекциям с помощью цепных методов и анонимного интерфейса, такого как Linq в .NET. В отличие от большинства других библиотек коллекций, использующих статические методы, необходимо выполнять итерацию всей коллекции, Diting предоставляет базовый класс Enumerable, который содержит отложенные цепочечные методы для реализации запроса к коллекции или массиву.

Поддерживаемые методы: любой, приведение, контакт, содержит, считать, отличить, elementAt, кроме, first, firstOrDefault, groupBy, interset, join, last, lastOrDefault, ofType, orderBy, orderByDescending, обратный, select, selectMany, single, singleOrDefault, пропустить , skipWhile, take, takeWhile, toArray, toArrayList, union, где


1

Scala.Now я прочитал это, и нашел это как linq, но более простой и более нечитаемый. но Scala может работать в Linux, да? Csharp нужно моно.


1
Для запуска Scala требуется среда выполнения Java: она не обязательно будет работать при установке на чистом Linux, в зависимости от того, какие компоненты вы устанавливаете.
Rup

@Rup есть полностью совместимая JRE для GNU / Linux, и Mono не является полностью совместимой реализацией .NET.
Отображаемое имя

@Sarge Это не моя точка зрения, но Mono достаточно хорошо запускает LINQ, не так ли? Кроме того, теперь есть собственное ядро Microsoft .Net для Linux .
Rup

(GNU /) Linux не единственная платформа, кроме Windows, и JRE существует для самых разных платформ. Mono не полностью реализует все, например, нет WPF.
Отображаемое имя

0

Был язык программирования Pizza (расширение Java), и вы должны взглянуть на него. - Он использует концепцию «плавных интерфейсов» для запроса данных декларативным образом, и это в принципе идентично LINQ без выражений запросов (http://en.wikipedia.org/wiki/Pizza_programming_language). Но, увы, это не преследовалось, но это был бы один из способов получить что-то похожее на LINQ в Java.


1
Конечно это преследовалось, только не под названием «Пицца». Обобщения из Pizza были объединены в GJ, который затем стал ссылочным компилятором Java 1.3 (хотя обобщения были скрыты за флагом до 1.5). В то же время ... остальные идеи, плюс несколько дополнительных, стали Scala.
Кевин Райт

Спасибо за эту информацию, конечно, Scala является хорошим моментом здесь. Но эти возможности не интегрированы в язык Java. Вы можете использовать язык Scala для реализации красивого кода запроса и использовать полученный бинарный файл из Java.
Нико

Также смотрите ONGL на commons.apache.org/proper/commons-ognl , который используется и поддерживается.
Нико


0

Вы можете попробовать эту библиотеку: https://code.google.com/p/qood/

Вот несколько причин, чтобы использовать его:

  1. легкий: всего 9 открытых интерфейсов / класс для изучения.
  2. запрос, такой как SQL: поддержка группировки, упорядочение, левое соединение, формула и т. д.
  3. для больших данных: используйте File (QFS) вместо Heap Memory.
  4. попытаться решить объектно-реляционное несоответствие импеданса .
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.