Language-Integrated Query (LINQ) was created for C# by Microsoft. It's a way of retrieving and sorting data in arrays, using strongly typed collections of objects, and using familiar operators and functions used in languages like SQL. More details can be found here: (https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/)
ect-java-linq draws inspiration from LINQ and brings this inspiration to Java. One of the great ideas in LINQ was the ability to chain methods, and this is also built as standard in this small, dependency-free Java 17 library, bringing fluent querying to Java collections and streams.
ect-java-linq wraps a Supplier<Stream<T>> so you can build lazy, chainable pipelines (e.g. where().select().orderBy().skip().take()) and then materialise results with toList(), toSet(), toMap(), etc.
The API is intentionally familiar to anyone who’s used LINQ.
Java Streams are powerful, but they are:
- “one-shot” by default (a
Streamcan only be consumed once), and - not always ergonomic for common LINQ-style operations.
ect-java-linq's aim is to simplify the querying of streams, arrays, iterators, lists and sets.
The ect-java-linq holds Linq that provides a re-iterable (via Supplier<Stream>) as the basis for all actions.
Methods like add, remove, clear in this library are functional. They do not mutate the original source collection.
From the library project folder:
mvn clean installThen in your consuming project’s pom.xml:
<dependency>
<groupId>tech.ect</groupId>
<artifactId>ect-java-linq</artifactId>
<version>0.1.0</version>
</dependency>Get all users, where we are only interested in active users, order then by last name, and skip to the 2nd page of results, based on 10 records per page:
var page = Linq.from(users)
.where(u -> u.isActive())
.orderBy(User::getLastName)
.skip(10)
.take(10)
.toList();Group all users by department:
var groups = Linq.from(users)
.groupByList(User::getDepartment);
for (var g : groups) {
System.out.println("Dept: " + g.key());
var names = g.records().select(User::getName).toList();
}Get a list of distinct user email addresses:
var distinctUsers = Linq.from(users)
.distinctBy(User::getEmail)
.toList();Get a list of orders, linked to customers, where order.customerId = customer.id, then show the customer name in a list:
var joined = Linq.from(orders)
.innerJoin(
customers,
Order::getCustomerId,
Customer::getId,
(order, customer) -> order.getId() + " -> " + customer.getName()
)
.toList();The from function allows you to define your base/source. The available options are:
static <T> Linq<T> from(Iterable<T> iterable)static <T> Linq<T> from(Collection<T> items)static <T> Linq<T> from(Stream<T> stream)Buffers the stream to a list to keep the sequence reusable.static <T> Linq<T> fromSupplier(Supplier<Stream<T>> supplier)
Predicates mean that we can define what you are look for easily e.g. u -> u.id === 1 etc.
Where, select and selectMany can act immediately on the return from a from function.
Linq<T> where(Predicate<? super T> predicate)<R> Linq<R> select(Function<? super T, ? extends R> selector)<R> Linq<R> selectMany(Function<? super T, ? extends Stream<? extends R>> selector)
<K> Map<K, List<T>> groupBy(Function<? super T, ? extends K> keySelector)<K> List<Group<K, T>> groupByList(Function<? super T, K> keySelector)ReturnsGroup<K, T>objects containing:key()– the group keyrecords()– aLinq<T>for that group’s items
<K extends Comparable<? super K>> Linq<T> orderBy(Function<? super T, ? extends K> keySelector)<K extends Comparable<? super K>> Linq<T> orderByDescending(Function<? super T, ? extends K> keySelector)<K extends Comparable<? super K>> Linq<T> orderByNullsFirst(Function<? super T, ? extends K> keySelector)<K extends Comparable<? super K>> Linq<T> orderByNullsLast(Function<? super T, ? extends K> keySelector)<K extends Comparable<? super K>> Linq<T> orderByDescendingNullsFirst(Function<? super T, ? extends K> keySelector)<K extends Comparable<? super K>> Linq<T> orderByDescendingNullsLast(Function<? super T, ? extends K> keySelector)Linq<T> orderBy(Comparator<? super T> comparator)Linq<T> orderByDescending(Comparator<? super T> comparator)
Linq<T> skip(long count)Linq<T> take(long count)Linq<T> skipAndTake(long skip, long take)Linq<T> takeLast(int count)
Linq<T> distinct()<K> Linq<T> distinctBy(Function<? super T, ? extends K> keySelector)Linq<T> except(Collection<? extends T> other)Linq<T> except(Iterable<? extends T> other)Linq<T> intersect(Collection<? extends T> other)Linq<T> union(Iterable<? extends T> other)
Linq<T> reverse()
-
<TInner, K, R> Linq<R> innerJoin(Iterable<TInner> inner, Function<? super T, ? extends K> outerKeySelector, Function<? super TInner, ? extends K> innerKeySelector, BiFunction<? super T, ? super TInner, ? extends R> resultSelector) -
<TInner, K, R> Linq<R> leftOuterJoin(Iterable<TInner> inner, Function<? super T, ? extends K> outerKeySelector, Function<? super TInner, ? extends K> innerKeySelector, BiFunction<? super T, Optional<TInner>, ? extends R> resultSelector)
Optional<T> firstOptional()T first()T last()T lastOrNull()Optional<T> lastOptional()T single()
List<T> toList()Set<T> toSet()<K, V> Map<K, V> toMap(Function<? super T, ? extends K> keySelector, Function<? super T, ? extends V> valueSelector)<K, V> Map<K, V> toMap(Function<? super T, ? extends K> keySelector, Function<? super T, ? extends V> valueSelector, BinaryOperator<V> merge)
boolean any(Predicate<? super T> predicate)boolean all(Predicate<? super T> predicate)boolean contains(T item)<K> boolean containsBy(Function<? super T, ? extends K> keySelector, K key)boolean isEmpty()boolean sequenceEqual(Iterable<? extends T> other)boolean sequenceEqual(Iterable<? extends T> other, BiPredicate<? super T, ? super T> equalsFn)
long count()<R extends Comparable<? super R>> R min(Function<? super T, ? extends R> selector)<R extends Comparable<? super R>> R max(Function<? super T, ? extends R> selector)double sum(ToDoubleFunction<? super T> selector)OptionalDouble averageOptional(ToDoubleFunction<? super T> selector)double average(ToDoubleFunction<? super T> selector)int sumInt(ToIntFunction<? super T> selector)long sumLong(ToLongFunction<? super T> selector)
These return a new Linq<T> and do not change the original source:
Linq<T> add(T item)Linq<T> addAll(Iterable<? extends T> items)Linq<T> remove(T item)Linq<T> removeAll(Collection<? extends T> items)Linq<T> clear()
None
If you find some benefit from using this package, please consider the time it took to put this together, and why not buy me a coffee? Goodness only knows that most of us would not function without coffee. All donations very much welcomed: (https://www.buymeacoffee.com/exoduscloudtech)
To get more help on the this ECT Java Linq, please visit (https://angular-grid.net/free/)
array java linq sql
1.0
MIT
Copyright © 2010–2026 Exodus Cloud Technology Solutions Ltd.
Registered in England & Wales. Company No 7340061.