零依赖 · 50KB · JDK 8+ · MIT 开源

SQL 思维 查询 Java 内存数据

Linq.J 将 C# LINQ 的强大能力带入 Java 世界。通过优雅的链式 API,
像写 SQL 一样对 List、Array、Stream 等内存数据进行关联、筛选、排序和聚合。

QueryDemo.java
LIVE EXAMPLE
var result = Linq.from(employees)
    .innerJoin(departments, Dept::getId, Emp::getDeptId)
    .where(Emp::getSalary, salary -> salary > 5000)
    .groupBy(Dept::getName)
    .select(
        Columns.of(Dept::getName, "department"),
        Columns.avg(Emp::getSalary, "avgSalary"),
        Columns.count("headcount")
    )
    .orderByDesc(Emp::getSalary)
    .write(DeptStats.class);
Java 8+ 类型安全 链式调用 零依赖
0
外部依赖
~50KB
体积大小
JDK 8+
最低版本
MIT
开源协议

为什么选择 Linq.J?

轻量、强大、优雅 — 用最少的代码完成最复杂的数据查询

零依赖 · 极致轻量

运行时无任何第三方依赖,仅 50KB 大小。引入即用,不会给项目带来任何负担。

类 SQL 链式语法

Select、Join、Where、Group By、Order By、Limit… 用你熟悉的 SQL 思维操作内存数据。

类型安全

基于 Lambda 方法引用的列操作,编译期检查字段名,IDE 自动补全,告别魔法字符串。

多数据源支持

List、Array、SQL 结果集、CSV/JSON/XML、Stream… 任何内存中的集合都能查询。

可插拔查询引擎

抽象 Engine 接口,默认 EruptEngine 内置 Hash Join 等高效策略,可自定义扩展。

丰富的聚合函数

COUNT、SUM、AVG、MAX、MIN、COUNT DISTINCT… 完整的聚合能力,配合 Group By 使用。

完整的 SQL 操作对应

Linq.J 提供了与 SQL 一一对应的操作方法,链式调用一气呵成

FROM
JOIN
WHERE
GROUP BY
SELECT
HAVING
ORDER BY
LIMIT
WRITE
JOIN 关联查询
leftJoin() rightJoin() innerJoin() fullJoin()
WHERE 条件过滤
eq() like() between() in() isNull() gt() / lt() where(λ)
SELECT 投影与聚合
select(Class) select(Field...) count() sum() avg() max() / min()
WRITE 结果写出
write(Class) writeOne(Class) writeMap() writeMapOne()

直观感受 Linq.J 的优雅

像写 SQL 一样操作 Java 对象,代码即文档

简洁强大的基础查询

从简单的排序过滤到复合操作,一行代码搞定。支持原始类型和自定义对象。

  • 支持原始类型直接查询
  • 链式调用自然流畅
  • 结果自动映射到目标类型
BasicQuery.java
// 字符串排序过滤
var strings = Linq.from("C", "A", "B", "B")
    .gt(Th::is, "A")
    .orderByDesc(Th::is)
    .write(String.class);
// 结果: [C, B, B]

// 数字排序
var integers = Linq.from(1, 2, 3, 7, 6, 5)
    .orderBy(Th::is)
    .write(Integer.class);
// 结果: [1, 2, 3, 5, 6, 7]

强大的多表关联

支持四种标准 JOIN 操作,使用 Hash 策略实现高效关联,语法与 SQL 完全对应。

  • LEFT / RIGHT / INNER / FULL JOIN
  • Hash Join 高效引擎
  • Lambda 类型安全关联键
JoinQuery.java
// Left Join + 多表 Select
Linq.from(source)
    .leftJoin(target, Target::getId, Source::getId)
    .select(Source.class)
    .select(Target::getName)
    .write(Result.class);

// Inner Join + Where + Distinct
var names = Linq.from(data)
    .innerJoin(target, Target::getId, Data::getId)
    .like(Data::getName, "a")
    .select(Data::getName)
    .distinct()
    .orderBy(Data::getName)
    .write(String.class);

灵活的条件过滤

从简单的等值比较到复杂的自定义条件,WHERE 子句覆盖你的所有需求。

  • eq / between / in / like / isNull
  • 单字段 Lambda 条件
  • 多字段自定义组合条件
WhereQuery.java
// 精确匹配
Linq.from(source).eq(User::getName, "Thanos");

// 范围查询
Linq.from(source).between(User::getId, 1, 100);

// 自定义单字段条件
Linq.from(source).where(User::getId, id -> id >= 5);

// 多字段组合条件
Linq.from(source).where(row -> {
    String name = row.get(User::getName);
    Integer age = (Integer) row.get(User::getAge);
    return "admin".equals(name) || age > 18;
});

分组与聚合

Group By + 聚合函数 + Having,完整的分组聚合能力,生成统计报表轻而易举。

  • GROUP BY 分组
  • HAVING 过滤
  • 多聚合函数组合
GroupByQuery.java
Linq.from(source)
    .groupBy(Order::getCategory)
    .select(
        Columns.of(Order::getCategory, "name"),
        Columns.min(Order::getDate, "earliest"),
        Columns.avg(Order::getPrice, "avgPrice"),
        Columns.count("total"),
        Columns.countDistinct(
            Order::getBuyer, "uniqueBuyers"
        )
    )
    .having(row ->
        Integer.parseInt(
            row.get("total").toString()
        ) > 10
    )
    .orderBy(Order::getPrice)
    .write(CategoryStats.class);

灵活的结果写出

查询结果可以映射为 Java 对象、List、Map 或单个值,满足不同场景需求。

  • write() → List<T>
  • writeOne() → T
  • writeMap() → List<Map>
  • writeMapOne() → Map
WriteResult.java
// 写出为对象列表
List<User> list = Linq.from(source)
    .orderByAsc(User::getDate)
    .write(User.class);

// 写出单个对象
User one = Linq.from(source)
    .limit(1)
    .writeOne(User.class);

// 写出为 Map 列表
List<Map<String, Object>> maps =
    Linq.from(source).writeMap();

// 写出单个 Map
Map<String, Object> map =
    Linq.from(source).writeMapOne();

清晰的分层设计

查询构建与执行引擎解耦,接口隔离,灵活可扩展

链式 API 层
Select
Join
Where
GroupBy
OrderBy
Write
查询模型层
Linq (门面)
Dql (查询状态)
Column / Row
执行引擎层
Engine (抽象)
EruptEngine (默认)
Custom Engine
Lambda 解析层
SFunction
LambdaSee
SerializedLambda

在哪里使用 Linq.J?

分布式微服务、数据处理、报表生成… 无处不在

01

RPC 结果关联

Feign / Dubbo / gRPC 等微服务调用返回的多个结果集,通过 Linq.J 在内存中进行 JOIN 关联,替代多次数据库查询。

02

异构数据计算

Redis、MongoDB、MySQL 等不同数据源的结果,统一加载到内存后,用 Linq.J 进行跨源查询与聚合。

03

SQL 结果再加工

数据库查询结果需要进一步排序、过滤、聚合?Linq.J 让代码替代复杂的二次 SQL,逻辑清晰可维护。

04

内存分页与排序

多结果合并后的排序聚合与内存分页,告别手写 for 循环和 if 分支,代码量减少 80%。

05

对象转换映射

语义化地完成对象转换与映射,代码即文档,团队协作更清晰敏捷。

06

跨数据源联邦查询

不同系统、不同存储的数据,通过 Linq.J 在应用层实现联邦访问,无需数据迁移。

三步上手 Linq.J

零配置,即装即用

1

添加 Maven 依赖

pom.xml
<dependency>
    <groupId>xyz.erupt</groupId>
    <artifactId>linq.j</artifactId>
    <version>LATEST</version>
</dependency>
2

确保字段有 Getter

User.java
@Getter  // Lombok 注解
public class User {
    private Long id;
    private String name;
    private Integer age;
}
3

开始查询

Main.java
List<User> adults = Linq.from(users)
    .where(User::getAge, age -> age >= 18)
    .select(User::getName, User::getAge)
    .orderBy(User::getAge)
    .write(User.class);

传统写法 vs Linq.J

传统 Java 写法
Traditional.java
Map<String, List<Order>> grouped = new HashMap<>();
for (Order o : orders) {
    if (o.getAmount() > 100) {
        grouped.computeIfAbsent(
            o.getCategory(),
            k -> new ArrayList<>()
        ).add(o);
    }
}
Map<String, Double> avgMap = new HashMap<>();
for (var entry : grouped.entrySet()) {
    double sum = 0;
    for (var o : entry.getValue()) {
        sum += o.getAmount();
    }
    avgMap.put(entry.getKey(),
        sum / entry.getValue().size());
}
// 还需要排序... 更多代码...
VS
Linq.J 写法
LinqWay.java
var result = Linq.from(orders)
    .where(Order::getAmount,
        a -> a > 100)
    .groupBy(Order::getCategory)
    .select(
        Columns.of(
            Order::getCategory, "cat"),
        Columns.avg(
            Order::getAmount, "avg"),
        Columns.count("cnt")
    )
    .orderByDesc(Order::getAmount)
    .write(Stats.class);

// 清晰 · 简洁 · 高效

持续进化中

Linq.J 正在不断完善,更多强大特性即将到来

已完成

HAVING 支持

分组聚合后的条件过滤

已完成

分组列格式化

支持 group by date(created_at) 等表达式

计划中

集合操作

UNION ALL、UNION、INTERSECT、EXCEPT、UNION BY NAME

计划中

窗口函数

ROW_NUMBER、RANK、DENSE_RANK 等分析函数