掘金 后端 ( ) • 2024-05-06 11:44

🙏废话不多说系列,直接开整🙏

【提示】:这种框架本质是 将程序SQL语句用法衍生到 开发语言JAVA 中的一个实践。可以按照 SQL 的思维去学习这种类型的框架(比如还有:JDFrame 等)

女1.png


一、简单介绍

术语“LINQ to Objects”指直接将 LINQ 查询与任何 IEnumerable<T> 集合一起使用。 可以使用 LINQ 来查询任何可枚举的集合,例如 Primitive ArrayObject Array、 List、 Collection 或 Iterable 等等。 该集合可以是用户定义的集合,也可以是由 Java 开发包 API 返回的集合。

从根本上说,“LINQ to Objects”表示一种新的处理集合的方法。 采用旧方法,必须编写指定如何从集合检索数据的复杂的 foreach 循环。 而采用 LINQ 方法,只需编写描述要检索的内容的声明性代码。

此外,LINQ 查询与传统 foreach 循环相比具有两大优势:

  1. 它们更简明、更易读,尤其在筛选多个条件时。
  2. 它们使用最少的应用程序代码提供强大的筛选、排序和分组功能。

LINQ 查询与 Stream API 相比也具有一定优势:

  1. 支持 foreach 循环,因此你可以随时中断循环。
  2. 可以重复遍历 IEnumerable 接口对象。
  3. LINQ 非常易于使用,如 ToCollectionLeftJoin 等。
  4. 在大多数复杂情况下,LINQ 比 Stream API 更快。

通常,对数据执行的操作越复杂,就越能体会到 LINQ 相较于传统迭代技术的优势。

(1)特性

  • 实现了 LINQ to Objects 的所有 API。
  • 支持更多 API 和元组。
  • 支持 IEnumerable 和 Stream 互相转换。
  • 支持 Android。

image.png

(2)LINQ 的 API

  • empty
  • singleton
  • ofNullable
  • of
  • as
  • chars
  • words
  • lines
  • split
  • infinite
  • loop
  • enumerate
  • iterate
  • range
  • repeat

(3)IEnumerable 的 API

  • forEach
  • stream
  • parallelStream
  • aggregate
  • all
  • any
  • append
  • asEnumerable
  • average
  • cast
  • chunk
  • concat
  • contains
  • count
  • crossJoin
  • defaultIfEmpty
  • distinct
  • distinctBy
  • elementAt
  • elementAtOrDefault
  • except
  • exceptBy
  • findIndex
  • findLastIndex
  • first
  • firstOrDefault
  • format
  • fullJoin
  • groupBy
  • groupJoin
  • indexOf
  • intersect
  • intersectBy
  • join
  • joining
  • last
  • lastIndexOf
  • lastOrDefault
  • leftJoin
  • longCount
  • max
  • maxBy
  • min
  • minBy
  • ofType
  • orderBy
  • orderByDescending
  • prepend
  • reverse
  • rightJoin
  • runOnce
  • select
  • selectMany
  • sequenceEqual
  • shuffle
  • single
  • singleOrDefault
  • skip
  • skipLast
  • skipWhile
  • sum
  • take
  • takeLast
  • takeWhile
  • toArray
  • toCollection
  • toEnumeration
  • toLinkedList
  • toLinkedMap
  • toLinkedSet
  • toList
  • toLookup
  • toMap
  • toSet
  • union
  • unionBy
  • where
  • zip

(4)IGrouping(继承 IEnumerable) 的 API

  • getKey

(5)ILookup(继承 IEnumerable) 的 API

  • getCount
  • get
  • containsKey

(6)IOrderedEnumerable(继承 IEnumerable) 的 API

  • thenBy
  • thenByDescending

(7)Index 的 API

  • fromStart
  • fromEnd
  • getValue
  • isFromEnd
  • getOffset

(8)Range 的 API

  • startAt
  • endAt
  • getStart
  • getEnd
  • getOffsetAndLength

(9)元组类

  • Tuple1
  • Tuple2
  • Tuple3
  • Tuple4
  • Tuple5
  • Tuple6
  • Tuple7
  • TupleN

(10)调试视图 (IntelliJ IDEA)

  1. 打开设置对话框 File | Settings | Build, Execution, Deployment | Debugger | Data Views | Java Type Renderers
  2. 单击 Add 按钮。
  3. 在 Renderer name 输入 IterableView
  4. 在 Apply renderer to objects of type (fully-qualified name): 输入 java.lang.Iterable
  5. 在 When rendering a node 小节,选中 Use following expression: 并输入 DebugView.getDebuggerDisplayText(this)。 如果报错,按下 Alt + Enter 导入类。
  6. 选中 Use list of expression: 并在 Name 列输入 **RESULT VIEW**。 在 Expression 列输入DebugView.getDebuggerProxyObject(this)。 如果报错,按下 Alt + Enter 导入类。 建议选中 On-demand,以便在必要时枚举序列。
  7. 如果你想查看 Iterable 实例的默认字段,选中 Append default children
  8. 保存设置,尝试一下吧!

由于可能的副作用,应谨慎使用结果视图。

二、开始使用

(1)引入 Maven 或者 Gradle

<dependency>
    <groupId>com.bestvike</groupId>
    <artifactId>linq</artifactId>
    <version>6.0.0</version>
</dependency>

Gradle 用法:

implementation 'com.bestvike:linq:6.0.0'

(2)官方测试部分样例

  1. 拼接不为空的字符串
  2. 判断所有的正数是否全部为偶数;
  3. 判断所有的正数是否存在任一偶数;
  4. 在末尾追加一个数字并在头部插入两个数字;
  5. 计算整数序列的平均值;
  6. 连接两个整数序列;
 @Test
    void basicApiTest1() {

        // 拼接不为空的字符串
        var result = Linq.of("!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", Empty)
            .where(x -> x != null && !x.isEmpty())
            .aggregate((x, y) -> x + ", " + y);
        System.out.println("拼接不为空的字符串为:" + result);// !@#$%^, C, AAA, Calling Twice, SoS

        // 判断所有的正数是否全部为偶数。
        boolean resultBoolean = Linq.of(9999, 0, 888, -1, 66, -777, 1, 2, -12345)
                .where(x -> x > 0)
                .all(x -> x % 2 == 0);
        System.out.println("判断所有的正数是否全部为偶数:" + resultBoolean);// false

        // 判断所有的正数是否存在任一偶数。
        boolean resultBoolean2 = Linq.of(9999, 0, 888, -1, 66, -777, 1, 2, -12345)
                .where(x -> x > 0)
                .any(x -> x % 2 == 0);
        System.out.println("判断所有的正数是否存在任一偶数: " + resultBoolean2);// true

        // 在末尾追加一个数字并在头部插入两个数字
        String result3 = Linq.range(3, 2).append(5).prepend(2).prepend(1).format();
        System.out.println("在末尾追加一个数字并在头部插入两个数字: " + result3);//  [1, 2, 3, 4, 5]

        // 计算整数序列的平均值。
        // 如果源数据为int则使用 averageInt()
        double result4 = Linq.of(5, -10, 15, 40, 28).averageInt(); //15.6
        // [注意-要求所有的数据按照统一类型数据表示]如果源数据为double则使用 averageDouble()
        var result5 = Linq.of(5.6D, -12.0, 15D, 40D, 28D).averageDouble();// 15.319999999999999
        System.out.println("平均值:" + result4 + "  " + result5);// 平均值:15.6  15.319999999999999

        // 连接两个整数序列。
        String str = Linq.of(1, 2).concat(Linq.of(5, 6)).concat(Linq.of(9, 10)).format();
        System.out.println("连接两个整数序列:" + str);// [1, 2, 5, 6, 9, 10]

        List<String> s1 = Arrays.asList("one", "two");
        String string = Linq.of(s1).concat(Linq.of(s1)).format(Formatter.DEFAULT);
        System.out.println(string);
    }

(2)自测 Linq部分API

  1. 初始化数据,切分字符串;
  2. 集合统计值(最大值,最小值,平均值,总和,数量);
  3. 集合切分成多个子集合;
  4. ……
@Test
void basicApiDemo() {
    // 1.Linq:切分字符串 直接转数组
    //Linq.split("1,2,3", ",").cast(Long.class).forEach(System.out::println);
    // 2.JDK8:
    Arrays.stream("1,2,3".split(",")).mapToInt(Integer::parseInt).forEach(System.out::println);

    // 2.1 linq: empty
    List<String> emptyList = new ArrayList<>();
    List<String> strings = Linq.of(emptyList).defaultIfEmpty(String.valueOf(Linq.split("0,0,0", ","))).stream().toList();
    System.out.println("空集合则默认集合得到数据:" + strings);

    List<Integer> intList = Linq.of(new int[]{10, 2, 2, 1, 3, 1, 5, 6, 7, 8}).toList();
    int count = Linq.of(intList).count();
    Integer max = Linq.of(intList).max();
    int min = Linq.of(intList).min();
    double averageInt = Linq.of(intList).averageInt();
    int sumInt = Linq.of(intList).sumInt();
    System.out.println("数量:" + count + " 最大值:" + max + " 最小值:" + min + " 平均值:" + averageInt + " 总和:" + sumInt);
    List<String> strIntList = intList.stream().map(String::valueOf).toList();
    System.out.println("JDK 数字集合转字符集合:" + JSONUtil.toJsonStr(strIntList));
    System.out.println("分组:将集合按照2个元素分组划分");
    List<Integer[]> list = Linq.of(intList).chunk(4, Integer.class).toList();
    list.forEach(integers -> System.out.println(JSONUtil.toJsonStr(integers)));

    // 集合去重 + 倒序输出
    List<Integer> distinctIntList = Linq.of(intList).stream().sorted().distinct().toList();
    distinctIntList = Linq.of(distinctIntList).reverse().toList();
    System.out.println(JSONUtil.toJsonStr(distinctIntList));

    //List<String> intStrList = Linq.of(intList).cast(String.class).toList();
    //intStrList.forEach(System.out::println);
}

(4)🙏 献上:完整亲测代码 🌟

【1】完整代码

import cn.hutool.json.JSONUtil;
import com.bestvike.Index;
import com.bestvike.linq.Linq;
import com.bestvike.linq.util.Formatter;
import lombok.Builder;
import lombok.Data;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static com.bestvike.linq.util.Strings.Empty;

@SpringBootTest
class LinqTests {

    @Test
    void contextLoads() {
    }

    @Test
    void basicApiDemo() {
        // 1.Linq:切分字符串 直接转数组
        //Linq.split("1,2,3", ",").cast(Long.class).forEach(System.out::println);
        // 2.JDK8:
        Arrays.stream("1,2,3".split(",")).mapToInt(Integer::parseInt).forEach(System.out::println);

        // 2.1 linq: empty
        List<String> emptyList = new ArrayList<>();
        List<String> strings = Linq.of(emptyList).defaultIfEmpty(String.valueOf(Linq.split("0,0,0", ","))).stream().toList();
        System.out.println("空集合则默认集合得到数据:" + strings);

        List<Integer> intList = Linq.of(new int[]{10, 2, 2, 1, 3, 1, 5, 6, 7, 8}).toList();
        int count = Linq.of(intList).count();
        Integer max = Linq.of(intList).max();
        int min = Linq.of(intList).min();
        double averageInt = Linq.of(intList).averageInt();
        int sumInt = Linq.of(intList).sumInt();
        System.out.println("数量:" + count + " 最大值:" + max + " 最小值:" + min + " 平均值:" + averageInt + " 总和:" + sumInt);
        List<String> strIntList = intList.stream().map(String::valueOf).toList();
        System.out.println("JDK 数字集合转字符集合:" + JSONUtil.toJsonStr(strIntList));
        System.out.println("分组:将集合按照2个元素分组划分");
        List<Integer[]> list = Linq.of(intList).chunk(4, Integer.class).toList();
        list.forEach(integers -> System.out.println(JSONUtil.toJsonStr(integers)));

        // 集合去重 + 倒序输出
        List<Integer> distinctIntList = Linq.of(intList).stream().sorted().distinct().toList();
        distinctIntList = Linq.of(distinctIntList).reverse().toList();
        System.out.println(JSONUtil.toJsonStr(distinctIntList));

        //List<String> intStrList = Linq.of(intList).cast(String.class).toList();
        //intStrList.forEach(System.out::println);


    }

    @Test
    void basicApiTest1() {

        // 拼接不为空的字符串
        var result = Linq.of("!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", Empty)
                .where(x -> x != null && !x.isEmpty())
                .aggregate((x, y) -> x + ", " + y);
        System.out.println("拼接不为空的字符串为:" + result);// !@#$%^, C, AAA, Calling Twice, SoS

        // 判断所有的正数是否全部为偶数。
        boolean resultBoolean = Linq.of(9999, 0, 888, -1, 66, -777, 1, 2, -12345)
                .where(x -> x > 0)
                .all(x -> x % 2 == 0);
        System.out.println("判断所有的正数是否全部为偶数:" + resultBoolean);// false

        // 判断所有的正数是否存在任一偶数。
        boolean resultBoolean2 = Linq.of(9999, 0, 888, -1, 66, -777, 1, 2, -12345)
                .where(x -> x > 0)
                .any(x -> x % 2 == 0);
        System.out.println("判断所有的正数是否存在任一偶数: " + resultBoolean2);// true

        // 在末尾追加一个数字并在头部插入两个数字
        String result3 = Linq.range(3, 2).append(5).prepend(2).prepend(1).format();
        System.out.println("在末尾追加一个数字并在头部插入两个数字: " + result3);//  [1, 2, 3, 4, 5]

        // 计算整数序列的平均值。
        // 如果源数据为int则使用 averageInt()
        double result4 = Linq.of(5, -10, 15, 40, 28).averageInt(); //15.6
        // [注意-要求所有的数据按照统一类型数据表示]如果源数据为double则使用 averageDouble()
        var result5 = Linq.of(5.6D, -12.0, 15D, 40D, 28D).averageDouble();// 15.319999999999999
        System.out.println("平均值:" + result4 + "  " + result5);// 平均值:15.6  15.319999999999999

        // 连接两个整数序列。
        String str = Linq.of(1, 2).concat(Linq.of(5, 6)).concat(Linq.of(9, 10)).format();
        System.out.println("连接两个整数序列:" + str);// [1, 2, 5, 6, 9, 10]

        List<String> s1 = Arrays.asList("one", "two");
        String string = Linq.of(s1).concat(Linq.of(s1)).format(Formatter.DEFAULT);
        System.out.println(string);
    }

    @Test
    void updateAddress() {
        System.out.println(Index.fromStart(2));
        System.out.println(Linq.lines("HELLO WORLD").reverse().toList());
    }

    private static List<User> users = new ArrayList<>();
    private static List<Dept> depts = new ArrayList<>();
    private static List<UserDept> userDepts = new ArrayList<>();

    static {
        // 用户数据初始化
        users.add(User.builder().userId(1).userName("bob").userAge(23).score(75.3).delFlag(0).createTime(LocalDateTime.now()).build());
        users.add(User.builder().userId(2).userName("Allen").userAge(33).score(95D).delFlag(0).createTime(LocalDateTime.now()).build());
        users.add(User.builder().userId(3).userName("Mary").userAge(23).score(60D).delFlag(0).createTime(LocalDateTime.now()).build());
        users.add(User.builder().userId(4).userName("King").userAge(28).score(56.5).delFlag(0).createTime(LocalDateTime.now()).build());
        users.add(User.builder().userId(5).userName("张三").userAge(30).score(85.5).delFlag(0).createTime(LocalDateTime.now()).build());
        users.add(User.builder().userId(6).userName("李四").userAge(30).score(85.6).delFlag(1).createTime(LocalDateTime.now()).build());
        // 部门数据初始化
        depts.add(Dept.builder().deptId(1000).deptName("技术部").deptCode("IT").build());
        depts.add(Dept.builder().deptId(1001).deptName("财务部").deptCode("MB").build());
        depts.add(Dept.builder().deptId(1002).deptName("商务部").deptCode("MA").build());
        depts.add(Dept.builder().deptId(1003).deptName("人事部").deptCode("HR").build());
        // 用户部门分配情况初始化
        userDepts.add(UserDept.builder().deptId(1000).userId(1).build());
        userDepts.add(UserDept.builder().deptId(1000).userId(2).build());
        userDepts.add(UserDept.builder().deptId(1000).userId(5).build());
        userDepts.add(UserDept.builder().deptId(1002).userId(2).build());
        userDepts.add(UserDept.builder().deptId(1002).userId(1).build());
        userDepts.add(UserDept.builder().deptId(1003).userId(3).build());
        userDepts.add(UserDept.builder().deptId(1003).userId(4).build());
    }


    public static void main(String[] args) {
        System.out.println("=============================== 对象集合处理 =============================");
        System.out.println("[排序]按照用户年龄升序:");
        Linq.of(users).orderBy(User::getUserAge).toList().forEach(System.out::println);
        System.out.println("[排序]按照用户年龄升序、成绩降序:(注意:此写法只能按照最后一个排序逻辑处理)⚠️");
        Linq.of(users).orderBy(User::getUserAge).orderByDescending(User::getScore).toList().forEach(System.out::println);
        System.out.println("[排序]按照用户年龄降序:");
        Linq.of(users).orderByDescending(User::getUserAge).toList().forEach(System.out::println);
        System.out.println("[排序]按照用户姓名降序:(支持中英文混合排序-中文转成拼音按照字母先后顺序排序)");
        Linq.of(users).orderByDescending(User::getUserName).toList().forEach(System.out::println);


        System.out.println("【筛选】年龄在30岁及以上的用户:");// 类似SQL select * from user where user_age >= 30;
        Linq.of(users).where(user -> user.getUserAge() >= 30).toList().forEach(System.out::println);
        System.out.println("【筛选】年龄在30岁以下并且分数在60以下的用户:");// ≈  select * from user here user_ge < 30 and score < 60;
        Linq.of(users).where(user -> user.getUserAge() < 30 && user.getScore() < 60D).toList().forEach(System.out::println);
        System.out.println("【筛选】模糊查询 - 根据查找名字中带有‘三’的用户:");// ≈ select * from user where user_name like '%三%';
        Linq.of(users).where(user -> user.getUserName().contains("三")).toList().forEach(System.out::println);
        System.out.println("【筛选】范围查询 - 查询前三个ID用户:");// ≈ select * from user where user_id in (1, 2, 3, 100);
        Linq.of(users).where(user -> Linq.of(1, 2, 3, 100).contains(user.getUserId())).toList().forEach(System.out::println);


        System.out.println("[统计] 最大,最小,总和,平均值,用户总数");
        // ≈ select max(user_age) from user;
        System.out.println("最大年龄:" + Linq.of(users).max(User::getUserAge));
        // ≈ select min(user_age) from user;
        System.out.println("最小年龄:" + Linq.of(users).min(User::getUserAge));
        // ≈ select avg(user_age) from user;
        System.out.println("平均年龄:" + Linq.of(users).averageDouble(User::getUserAge));
        // ≈ select sum(score) from user;
        System.out.println("总成绩:" + Linq.of(users).averageDouble(User::getScore));
        // ≈ select count(1) from user;
        System.out.println("总用户数:" + Linq.of(users).count());
        // ≈ select count(1) from user where score < 90;
        System.out.println("分数<70的总用户数:" + Linq.of(users).count(user -> user.getScore() < 90D));

        System.out.println("最值 top ");
        System.out.println("同类第一个(1):" + Linq.of(users).where(user -> user.getUserAge() == 23).firstOrDefault());
        System.out.println("同类第一个(2):" + Linq.of(users).firstOrDefault(user -> user.getUserAge() == 23));
        System.out.println("同类最后一个(1):" + Linq.of(users).where(user -> user.getUserAge() == 23).lastOrDefault());
        System.out.println("同类最后一个(2):" + Linq.of(users).lastOrDefault(user -> user.getUserAge() == 23));
        // ≈ select * from (select ROW_NUMBER() over(order by age desc) as rowNum,*) t wher rowNum > 1
        System.out.println("跳过前面多少条数据,取剩下的数据: " + Linq.of(users).orderByDescending(User::getScore).skip(2));

        System.out.println("分页查询:");
        //跳过第一条,取两条,即取第二条到第四条
        // ≈ select * from (select ROW_NUMBER() over(order by age desc) as rowNum,*) t wher rowNum>1 and rowNum<=4
        List<User> tmpUsers = Linq.of(users).orderByDescending(User::getUserAge).skip(1).take(3).toList();
        tmpUsers.forEach(System.out::println);

        System.out.println("分组查询: ");
        Linq.of(users).groupBy(User::getUserAge).toList().forEach(item -> {
            System.out.println("年龄:" + item.getKey()
                    + " 总数:" + item.count(x -> x.getUserId() != null)
                    + " userId最大值:" + item.max(User::getUserId)
                    + " userId最小值:" + item.min(User::getUserId)
            );
        });

        System.out.println("=============================== 对象集合处理 =============================");
    }

}

@Data
@Builder
class User {
    private Integer userId;// ID
    private String userName;// 姓名
    private Integer userAge;// 年龄
    private Double score;// 评分
    private LocalDateTime createTime;
    private Integer delFlag;// 逻辑删除标识(0存在,1删除)
}

@Data
@Builder
class Dept {
    private Integer deptId;
    private String deptName;
    private String deptCode;
}

@Data
@Builder
class UserDept {
    private Integer deptId;
    private Integer userId;
    private Dept deptInfo;
    private User userInfo;
}

【2】测试结果

=============================== 对象集合处理 =============================
[排序]按照用户年龄升序:
User(userId=1, userName=bob, userAge=23, score=75.3, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
User(userId=3, userName=Mary, userAge=23, score=60.0, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
User(userId=4, userName=King, userAge=28, score=56.5, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
User(userId=5, userName=张三, userAge=30, score=85.5, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
User(userId=6, userName=李四, userAge=30, score=85.6, createTime=2024-05-01T13:44:25.886499300, delFlag=1)
User(userId=2, userName=Allen, userAge=33, score=95.0, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
[排序]按照用户年龄升序、成绩降序:(注意:此写法只能按照最后一个排序逻辑处理)⚠️
User(userId=2, userName=Allen, userAge=33, score=95.0, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
User(userId=6, userName=李四, userAge=30, score=85.6, createTime=2024-05-01T13:44:25.886499300, delFlag=1)
User(userId=5, userName=张三, userAge=30, score=85.5, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
User(userId=1, userName=bob, userAge=23, score=75.3, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
User(userId=3, userName=Mary, userAge=23, score=60.0, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
User(userId=4, userName=King, userAge=28, score=56.5, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
[排序]按照用户年龄降序:
User(userId=2, userName=Allen, userAge=33, score=95.0, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
User(userId=5, userName=张三, userAge=30, score=85.5, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
User(userId=6, userName=李四, userAge=30, score=85.6, createTime=2024-05-01T13:44:25.886499300, delFlag=1)
User(userId=4, userName=King, userAge=28, score=56.5, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
User(userId=1, userName=bob, userAge=23, score=75.3, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
User(userId=3, userName=Mary, userAge=23, score=60.0, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
[排序]按照用户姓名降序:(支持中英文混合排序-中文转成拼音按照字母先后顺序排序)
User(userId=5, userName=张三, userAge=30, score=85.5, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
User(userId=6, userName=李四, userAge=30, score=85.6, createTime=2024-05-01T13:44:25.886499300, delFlag=1)
User(userId=3, userName=Mary, userAge=23, score=60.0, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
User(userId=4, userName=King, userAge=28, score=56.5, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
User(userId=1, userName=bob, userAge=23, score=75.3, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
User(userId=2, userName=Allen, userAge=33, score=95.0, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
【筛选】年龄在30岁及以上的用户:
User(userId=2, userName=Allen, userAge=33, score=95.0, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
User(userId=5, userName=张三, userAge=30, score=85.5, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
User(userId=6, userName=李四, userAge=30, score=85.6, createTime=2024-05-01T13:44:25.886499300, delFlag=1)
【筛选】年龄在30岁以下并且分数在60以下的用户:
User(userId=4, userName=King, userAge=28, score=56.5, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
【筛选】模糊查询 - 根据查找名字中带有‘三’的用户:
User(userId=5, userName=张三, userAge=30, score=85.5, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
【筛选】范围查询 - 查询前三个ID用户:
User(userId=1, userName=bob, userAge=23, score=75.3, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
User(userId=2, userName=Allen, userAge=33, score=95.0, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
User(userId=3, userName=Mary, userAge=23, score=60.0, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
[统计] 最大,最小,总和,平均值,用户总数
最大年龄:33
最小年龄:23
平均年龄:27.833333333333332
总成绩:76.31666666666666
总用户数:6
分数<70的总用户数:5
最值 top 
同类第一个(1):User(userId=1, userName=bob, userAge=23, score=75.3, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
同类第一个(2):User(userId=1, userName=bob, userAge=23, score=75.3, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
同类最后一个(1):User(userId=3, userName=Mary, userAge=23, score=60.0, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
同类最后一个(2):User(userId=3, userName=Mary, userAge=23, score=60.0, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
跳过前面多少条数据,取剩下的数据: com.bestvike.linq.enumerable.OrderedPartition@1c53fd30
分页查询:
User(userId=5, userName=张三, userAge=30, score=85.5, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
User(userId=6, userName=李四, userAge=30, score=85.6, createTime=2024-05-01T13:44:25.886499300, delFlag=1)
User(userId=4, userName=King, userAge=28, score=56.5, createTime=2024-05-01T13:44:25.886499300, delFlag=0)
分组查询: 
年龄:23 总数:2 userId最大值:3 userId最小值:1
年龄:33 总数:1 userId最大值:2 userId最小值:2
年龄:28 总数:1 userId最大值:4 userId最小值:4
年龄:30 总数:2 userId最大值:6 userId最小值:5
=============================== 对象集合处理 =============================

三、官方案例

image.png

附录

🙏至此,非常感谢阅读🙏

女1.png