Java的jLinqer包介绍
1.介绍
熟悉C#的lambda 表达式,想要使用 LINQ 在 Java,是个问题,虽然 Java8用函数式接口已经实现了部分lambda 表达式,但是还是不够灵活。
2.Linqer简介
Linqer 是在 Java 中的可以使用 LINQ 语言集成查询 (LINQ)。可以弥补目前Java8在 LINQ方面的一些不足,实现了在 c# 中 的(selectMany,Union, Intersect, Except等)。
3.使用方法
如果你使用 Maven,请在以下 pom.xml 应用以下包。
<dependency> <groupId>com.github.jlinqer</groupId> <artifactId>jlinqer</artifactId> <version>1.0.0</version> </dependency>
如果没有使用Maven 时,直接使用 jLinqer jar,下载地址:
https://oss.sonatype.org/content/groups/public/com/github/jlinqer/jlinqer/1.0.0/jlinqer-1.0.0.jar
4.LINQ jLinqer 对比
功能 | LINQ(C#) | jLinqer(Java) | Stream(Java) |
---|---|---|---|
【基本】 | |||
筛选 | Where | where | filter |
投影 | Select | select | map |
排序(升序) | OrderBy | orderBy | sorted |
排序(降序) | OrderByDescending | orderByDescending | n/a |
按升序对序列中的元素执行后续排序 | ThenBy | thenBy | n/a |
按降序对序列中的元素执行后续排序。 | ThenByDescending | thenByDescending | n/a |
将序列的每个元素投影到 IEnumerable<T> 并将结果序列合并为一个序列。 | SelectMany | selectMany | flatMap |
【提取】 | |||
跳过序列中指定数量的元素,然后返回剩余的元素。 | Skip | skip | skip |
只要满足指定的条件,就跳过序列中的元素,然后返回剩余元素。 | SkipWhile | skipWhile | n/a |
从序列的开头返回指定数量的连续元素。 | Take | take | limit |
只要满足指定的条件,就会返回序列的元素,然后跳过剩余的元素。 | TakeWhile | takeWhile | n/a |
【合成】 | |||
连接两个序列 | Concat | concat | concat |
生成两个序列的交集 | Intersect | intersect | n/a |
生成两个序列的并集 | Union | union | n/a |
生成两个序列的差集 | Except | except | n/a |
基于匹配键对两个序列的元素进行关联 | Join | join | n/a |
基于键相等对两个序列的元素进行关联并对结果进行分组 | GroupJoin | groupJoin | n/a |
反转序列中元素的顺序 | Reverse | reverse | n/a |
将指定函数应用于两个序列的对应元素,以生成结果序列 | Zip | zip | n/a |
【分组和总计】 | |||
返回序列中的非重复元素 | Distinct | distinct | distinct |
累加器函数 | Aggregate | aggregate | reduce |
对序列中的元素进行分组 | GroupBy | groupBy | Collectors.groupingBy |
计算数值序列的平均值 | Average | averageXXX | Collectors.summarizingXXX |
返回序列中的元素数量 | Count | count | n/a |
返回一个 Int64,表示序列中的元素的数量 | LongCount | longCount | count |
返回值序列中的最大值 | Max | max | max |
返回值序列中的最小值 | Min | min | min |
计算数值序列之和 | Sum | sumXXX | Collectors.summarizingXXX |
返回序列中的第一个元素 | First | first | findFirst |
返回序列中的第一个元素;如果未找到元素,则返回默认值 | FirstOrDefault | firstOrDefault | n/a |
返回序列的最后一个元素 | Last | last | n/a |
返回序列中的最后一个元素;如果未找到元素,则返回默认值 | LastOrDefault | lastOrDefault | n/a |
返回值序列的单个特定元素 | Single | single | n/a |
返回序列中单个特定元素,如果未找到这样的元素,则返回默认值 | SingleOrDefault | singleOrDefault | n/a |
返回指定序列的元素;如果序列为空,则返回集合中的类型参数的默认值。 | DefaultIfEmpty | defaultIfEmpty | n/a |
返回序列中指定索引处的元素 | ElementAt | elementAt | n/a |
返回序列中指定索引处的元素;如果索引超出范围,则返回默认值 | ElementAtOrDefault | elementAtOrDefault | n/a |
确定序列中的所有元素是否满足条件 | All | all | allMatch |
确定序列中的任何元素是否存在或满足条件 | Any | any | anyMatch |
【区间】 | |||
返回一个具有指定的类型参数的空 | Empty | empty | n/a |
生成指定范围内的整数的序列 | Range | range | n/a |
生成包含一个重复值的序列 | Repeat | repeat | n/a |
【其他】 | |||
根据相等比较器确定两个序列是否相等 | SequenceEqual | sequenceEqual | n/a |
强制转换为指定的类型 | Cast | cast | n/a |
根据指定类型筛选 IEnumerable 的元素 | OfType | ofType | n/a |
5.使用方法
Where
1 List<Integer> list = new List<>(1, 2, 3); 2 3 List<Integer> actual = list.where(x -> x == 1 || x == 3).toList(); 4 5 assertEquals(true , actual.contains(1)); 6 assertEquals(false, actual.contains(2)); 7 assertEquals(true , actual.contains(3));
Select
1 List<Person> list = new List<>( 2 new Person("React" , 1), 3 new Person("Angular" , 3), 4 new Person("Backbone", 5) 5 ); 6 7 List<String> actual = list.select(x -> x.name).toList(); 8 9 assertEquals("React" , actual.get(0)); 10 assertEquals("Angular" , actual.get(1)); 11 assertEquals("Backbone", actual.get(2));
OrderBy
1 List<String> list = new List<>("Backbone", "Angular", "React"); 2 3 List<String> actual = list.orderBy(x -> x).toList(); 4 5 assertEquals("Angular" , actual.get(0)); 6 assertEquals("Backbone", actual.get(1)); 7 assertEquals("React" , actual.get(2));
OrderByDescending
1 List<String> list = new List<>("Backbone", "Angular", "React"); 2 3 List<String> actual = list.orderByDescending(x -> x).toList(); 4 5 assertEquals("React" , actual.get(0)); 6 assertEquals("Backbone", actual.get(1)); 7 assertEquals("Angular" , actual.get(2));
ThenBy
1 List<Person> list = new List<>( 2 new Person("Angular2", 2), 3 new Person("Angular1", 2), 4 new Person("React" , 1) 5 ); 6 7 List<String> actual = list.orderBy(x -> x.age).thenBy(x -> x.name).toList(); 8 9 assertEquals("React" , actual.get(0).name); 10 assertEquals("Angular1", actual.get(1).name); 11 assertEquals("Angular2" , actual.get(2).name);
ThenByDescending
1 List<Person> list = new List<>( 2 new Person("Angular2", 2), 3 new Person("Angular1", 2), 4 new Person("React" , 1) 5 ); 6 7 List<String> actual = list.orderBy(x -> x.age).thenByDescending(x -> x.name).toList(); 8 9 assertEquals("React" , actual.get(0).name); 10 assertEquals("Angular2", actual.get(1).name); 11 assertEquals("Angular1" , actual.get(2).name);
SelectMany
1 List<Person> list = new List<>( 2 new Person("Angular", 3, new List("1.0.1", "1.0.2")), 3 new Person("React" , 1, new List("2.0.1", "2.0.2")) 4 ); 5 6 List<String> actual = list.selectMany(x -> x.versionHistory).toList(); 7 8 assertEquals("1.0.1", actual.get(0)); 9 assertEquals("1.0.2", actual.get(1)); 10 assertEquals("2.0.1", actual.get(2)); 11 assertEquals("2.0.2", actual.get(3));
Skip
1 List<Integer> list = new List<>(1, 2, 3); 2 3 List<Integer> actual = list.skip(2).toList(); 4 5 assertEquals(3, actual.get(0).intValue());
SkipWhile
1 List<Integer> list = new List<>(1, 2, 3, 4, 5); 2 3 List<Integer> actual = list.skipWhile(x -> x <= 3).toList(); 4 5 assertEquals(4, actual.get(0).intValue()); 6 assertEquals(5, actual.get(1).intValue());
Take
1 List<String> list = new List<>("Backbone", "Angular", "React"); 2 3 List<String> actual = list.take(2).toList(); 4 5 assertEquals(2, actual.size()); 6 assertEquals("Backbone", actual.get(0)); 7 assertEquals("Angular" , actual.get(1));
TakeWhile
1 List<String> list = new List<>("Backbone", "Angular", "React"); 2 3 List<String> actual = list.takeWhile(x -> x.equals("Backbone") || x.equals("Angular")).toList(); 4 5 assertEquals(2, actual.size()); 6 assertEquals("Backbone", actual.get(0)); 7 assertEquals("Angular" , actual.get(1));
Concat
1 List<Integer> first = new List<>(1, 2); 2 List<Integer> second = new List<>(2, 3); 3 4 List<Integer> actual = first.concat(second).toList(); 5 6 assertEquals(1, actual.get(0).intValue()); 7 assertEquals(2, actual.get(1).intValue()); 8 assertEquals(2, actual.get(2).intValue()); 9 assertEquals(3, actual.get(3).intValue());
Intersect
1 List<Integer> first = new List<>(1, 2, 3); 2 List<Integer> second = new List<>(1, 3); 3 4 List<Integer> actual = first.intersect(second).toList(); 5 6 assertEquals(1, actual.get(0).intValue()); 7 assertEquals(3, actual.get(1).intValue());
Union
1 List<Integer> first = new List<>(1, 2, 3); 2 List<Integer> second = new List<>(0, 1, 3, 4); 3 4 List<Integer> actual = first.union(second).toList(); 5 6 assertEquals(5, actual.size()); 7 assertEquals(1, actual.get(0).intValue()); 8 assertEquals(2, actual.get(1).intValue()); 9 assertEquals(3, actual.get(2).intValue()); 10 assertEquals(0, actual.get(3).intValue()); 11 assertEquals(4, actual.get(4).intValue());
Except
1 List<Integer> first = new List<>(1, 2, 3); 2 List<Integer> second = new List<>(1, 3); 3 4 List<Integer> actual = first.except(second).toList(); 5 6 assertEquals(2, actual.get(0).intValue());
Join
1 List<Javascript> outer = new List<>( 2 new Javascript("Angular", 1), 3 new Javascript("React" , 4), 4 new Javascript("ES2016" , 5) 5 ); 6 List<Javascript> inner = new List<>( 7 new Javascript("Angular", 2), 8 new Javascript("Angular", 3), 9 new Javascript("ES2016" , 6), 10 new Javascript("ES7" , 7) 11 ); 12 13 Function<Javascript, String> outerKey = (x) -> x.name; 14 Function<Javascript, String> innerKey = (y) -> y.name; 15 BiFunction<Javascript, Javascript, Javascript> selector = (x, y) -> new Javascript(x.name, y.age); 16 List<Javascript> actual = outer.join(inner, outerKey, innerKey, selector).toList(); 17 18 assertEquals(3, actual.size()); 19 assertEquals("Angular", actual.get(0).name); 20 assertEquals("Angular", actual.get(1).name); 21 assertEquals("ES2016" , actual.get(2).name); 22 assertEquals(2, actual.get(0).age); 23 assertEquals(3, actual.get(1).age); 24 assertEquals(6, actual.get(2).age);
GroupJoin
1 List<Javascript> outer = new List<>( 2 new Javascript("Angular", 1), 3 new Javascript("React" , 4), 4 new Javascript("ES2016" , 5) 5 ); 6 List<Javascript> inner = new List<>( 7 new Javascript("Angular", 2), 8 new Javascript("Angular", 3), 9 new Javascript("ES2016" , 6), 10 new Javascript("ES7" , 7) 11 ); 12 13 Function<Javascript, String> outerKey = (x) -> x.name; 14 Function<Javascript, String> innerKey = (y) -> y.name; 15 BiFunction<Javascript, IEnumerable<Javascript>, Javascript> selector = (x, y) -> new Javascript(x.name, y.select(z -> z.age)); 16 List<Javascript> actual = outer.groupJoin(inner, outerKey, innerKey, selector).toList(); 17 18 assertEquals(3, actual.size()); 19 assertEquals("Angular", actual.get(0).name); 20 assertEquals("React" , actual.get(1).name); 21 assertEquals("ES2016" , actual.get(2).name); 22 assertEquals(2, actual.get(0).ages.elementAt(0)); 23 assertEquals(3, actual.get(0).ages.elementAt(1)); 24 assertEquals(0, actual.get(1).ages.count()); 25 assertEquals(6, actual.get(2).ages.elementAt(0));
Reverse
1 List<Integer> list = new List<>(1, 2, 3); 2 3 List<Integer> actual = list.reverse().toList(); 4 5 assertEquals(3, actual.get(0).intValue()); 6 assertEquals(2, actual.get(1).intValue()); 7 assertEquals(1, actual.get(2).intValue());
Zip
1 List<Integer> first = new List<>(1, 2, 3); 2 List<String> second = new List<>("Angular", "React", "Backbone"); 3 4 List<Integer> actual = first.zip(second, (x, y) -> String.format("%s %d", x, y)).toList(); 5 6 assertEquals("1 Angular" , actual.get(0)); 7 assertEquals("2 React" , actual.get(1)); 8 assertEquals("3 Backbone", actual.get(2));
Distinct
1 List<Integer> list =new List<>(1, 2, 3,1, 2, 3, 4); 2 3 List<Integer> actual = list.distinct().toList(); 4 5 assertEquals(1, actual.get(0).intValue()); 6 assertEquals(2, actual.get(1).intValue()); 7 assertEquals(3, actual.get(2).intValue()); 8 assertEquals(4, actual.get(3).intValue());
Aggregate
1 List<Integer> list = new List<>(1, 2, 3); 2 3 int actual = list.aggregate((sum, elem) -> sum + elem); 4 5 assertEquals(6, actual);
GroupBy
1 List<Person> list = new List<>( 2 new Person("React" , 1), 3 new Person("Angular" , 1), 4 new Person("Backbone", 5) 5 ); 6 7 Map<Integer, IEnumerable<Person>> actual = list.groupBy(x -> x.age); 8 9 assertEquals(true, actual.get(1).any(x -> x.name.equals("React"))); 10 assertEquals(true, actual.get(1).any(x -> x.name.equals("Angular"))); 11 assertEquals(true, actual.get(5).any(x -> x.name.equals("Backbone")));
Average
1 List<Long> listLong = new List<>(1l, 2l, 3l, 4l); 2 3 double actualLong = listLong.averageLong(x -> x); 4 5 assertEquals(2.5d, actualLong, 0);
Count
1 List<String> list = new List<>("Backbone", "Angular", "React"); 2 3 long actual = list.longCount(); 4 int actualNone = list.count(x -> x.equals("jquery")); 5 6 assertEquals(3, actual); 7 assertEquals(0, actualNone);
Max
1 List<Double> listDouble = new List<>(1d, 2d, 3d); 2 3 double actualDouble = listDouble.max(x -> x); 4 5 assertEquals(3d, actualDouble, 0);
Min
1 List<BigDecimal> listBigDecimal = new List<>( 2 new BigDecimal(1d), 3 new BigDecimal(2d), 4 new BigDecimal(3d) 5 ); 6 7 BigDecimal actualBigDecimal = listBigDecimal.min(x -> x); 8 9 assertEquals(1d, actualBigDecimal.doubleValue(), 0);
Sum
1 List<Integer> listInt = new List<>(1, 2, 3); 2 3 int actualInt = listInt.sumInt(x -> x); 4 5 assertEquals(6, actualInt);
FirstOrDefault
1 List<String> list = new List<>("Backbone", "Angular", "React"); 2 3 String actualFirst = list.firstOrDefault(); 4 String actualMatch = list.firstOrDefault(x -> x.equals("Angular")); 5 String actualUnMatch = list.firstOrDefault(x -> x.equals("jquery")); 6 7 assertEquals("Backbone", actualFirst); 8 assertEquals("Angular" , actualMatch); 9 assertEquals(null , actualUnMatch);
LastOrDefault
1 List<Integer> list = new List<>(1, 2, 3); 2 List<Integer> listEmpty = new List<>(); 3 4 int actual = list.lastOrDefault(); 5 Integer actualDefaultNone = listEmpty.lastOrDefault(x -> x == 0); 6 7 assertEquals(3, actual); 8 assertEquals(null, actualDefaultNone);
SingleOrDefault
1 List<Integer> listMany = new List<>(1, 2, 3); 2 List<Integer> listEmpty = new List<>(); 3 4 int actualFilter = listMany.singleOrDefault(x -> x == 3); 5 Integer actualUnMatch = listEmpty.singleOrDefault(x -> x == 0); 6 7 assertEquals(3, actualFilter); 8 assertEquals(null, actualUnMatch);
DefaultIfEmpty
1 List<String> listEmpty = new List<>(); 2 3 List<String> actualDefault = listEmpty.defaultIfEmpty("ES7").toList(); 4 5 assertEquals("ES7", actualDefault.get(0)); 6 ElementAtOrDefault 7 8 List<Integer> list = new List<>(1, 2, 3); 9 10 int actual = list.elementAtOrDefault(2); 11 Integer actualDefault = list.elementAtOrDefault(3); 12 13 assertEquals(3, actual); 14 assertEquals(null, actualDefault);
All
1 List<String> list = new List<>("Backbone", "Angular", "React"); 2 3 boolean actual = list.all(x -> x.equals("Angular") || x.equals("Backbone") || x.equals("React")); 4 boolean actualNotFound = list.all(x -> x.equals("Angular") || x.equals("React")); 5 6 assertEquals(true, actual); 7 assertEquals(false, actualNotFound);
Any
1 List<String> list = new List<>("Backbone", "Angular", "React"); 2 3 boolean actual = list.any(x -> x.equals("Angular")); 4 boolean actualNotFound = list.any(x -> x.equals("jquery")); 5 6 assertEquals(true, actual); 7 assertEquals(false, actualNotFound);
Empty
1 List<Double> actual = IEnumerable.empty(Double.class); 2 3 assertEquals(0, actual.count());
Range
1 List<Integer> actual = IEnumerable.range(-2, 3); 2 3 assertEquals(-2, actual.get(0).intValue()); 4 assertEquals(-1, actual.get(1).intValue()); 5 assertEquals(0 , actual.get(2).intValue());
Repeat
1 List<String> actual = IEnumerable.repeat(String.class, "Law of Cycles", 10); 2 3 assertEquals(10, actual.count()); 4 assertEquals("Law of Cycles", actual.get(9)); 5 SequenceEqual 6 7 List<Integer> first = new List<>(1, 2, 3); 8 List<Integer> secondMatch = new List<>(1, 2, 3); 9 List<Integer> secondUnMatchElem = new List<>(1, 2, 4); 10 11 boolean actualMatch = first.sequenceEqual(secondMatch); 12 boolean actualUnMatchElm = first.sequenceEqual(secondUnMatchElem); 13 14 assertEquals(true, actualMatch); 15 assertEquals(false, actualUnMatchElm);
Cast
1 List<Object> list = new List<>(1, 2, 3); 2 3 List<Integer> actual = list.cast(Integer.class).toList(); 4 5 assertEquals(1, actual.get(0).intValue()); 6 assertEquals(2, actual.get(1).intValue()); 7 assertEquals(3, actual.get(2).intValue());
OfType
1 List<Object> list = new List<>(1, "2", 3, "4"); 2 3 List<String> actualStr = list.ofType(String.class).toList(); 4 List<Integer> actualInt = list.ofType(Integer.class).toList(); 5 6 assertEquals("2", actualStr.get(0)); 7 assertEquals("4", actualStr.get(1)); 8 assertEquals(1 , actualInt.get(0).intValue()); 9 assertEquals(3 , actualInt.get(1).intValue());
6.源代码
https://github.com/k--kato/jLinqer