Skip to content

Commit 9c9b542

Browse files
committed
[add] add collecting examples of Stream API in java8 module.
1 parent b5aac3e commit 9c9b542

File tree

12 files changed

+396
-9
lines changed

12 files changed

+396
-9
lines changed

java8/README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,31 @@
1414
- Dish: 菜肴类,有一个静态属性的菜肴列表
1515
- StreamBasic: 指令式和函数式分别挑选低热量食物名
1616
- StreamOperation: 流操作(中间操作和终端操作)
17+
- Laziness: 流操作-中间操作
18+
- BuildingStreams: 构建流,从值序列,数组,文件来创建流。斐波拉切数列的几种生成方法
19+
1720

1821
使用流
1922

2023
- Filtering: 筛选(谓词筛选:filter;筛选互异的元素:distinct;忽略头几个元素:limit;截短至指定长度:skip)
2124
- Mapping: 映射
25+
- Finding: 查找和匹配
26+
- Reducing: 归约
2227
- PuttingIntoPractice: 各种流操作的使用示例
28+
- NumericStreams: 数值流(原始类型特化,数值范围)
29+
30+
用流收集数据
31+
32+
- Summarizing: 归约和汇总
33+
- Reducing: 收集器的灵活性,以不同的方法执行相同的操作
34+
- Grouping: 分组
35+
- Partitioning: 分区
36+
- GroupingTransactions: 分别使用指令式和函数式进行分组
37+
- ToListCollector: 自定义 ToListCollector,以及进行自定义收集而不去实现 Collector
38+
- PartitionPrimeNumbers: 将数字按质数和非质数分区;Collector 详解
39+
- CollectorHarness: 比较收集器的性能
40+
41+
42+
43+
44+

java8/src/main/java/com/brianway/learning/java8/streamapi/BuildingStreams.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,33 @@
99
import java.util.stream.Stream;
1010

1111
/**
12+
* 构建流:从值序列,数组,文件来创建流
1213
* 斐波拉切数列的几种生成方法
1314
*/
1415
public class BuildingStreams {
1516

1617
public static void main(String... args) throws Exception {
1718

19+
/**
20+
* 由值创建流
21+
*/
1822
// Stream.of
1923
Stream<String> stream = Stream.of("Java 8", "Lambdas", "In", "Action");
2024
stream.map(String::toUpperCase).forEach(System.out::println);
2125

2226
// Stream.empty
2327
Stream<String> emptyStream = Stream.empty();
2428

29+
/**
30+
* 由数组创建流
31+
*/
2532
// Arrays.stream
2633
int[] numbers = {2, 3, 5, 7, 11, 13};
2734
System.out.println(Arrays.stream(numbers).sum());
2835

36+
/**
37+
* 由函数生成流:创建无限流
38+
*/
2939
// Stream.iterate
3040
Stream.iterate(0, n -> n + 2)
3141
.limit(10)
@@ -68,6 +78,9 @@ public int getAsInt() {
6878
};
6979
IntStream.generate(fib).limit(10).forEach(System.out::println);
7080

81+
/**
82+
* 由文件生成流
83+
*/
7184
String path = BuildingStreams.class.getResource("/").getPath() + "/data-building.txt";
7285
long uniqueWords = Files.lines(Paths.get(path), Charset.defaultCharset())
7386
.flatMap(line -> Arrays.stream(line.split(" ")))

java8/src/main/java/com/brianway/learning/java8/streamapi/CollectorHarness.java renamed to java8/src/main/java/com/brianway/learning/java8/streamapi/collect/CollectorHarness.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.brianway.learning.java8.streamapi;
1+
package com.brianway.learning.java8.streamapi.collect;
22

33
import java.util.function.Consumer;
44

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package com.brianway.learning.java8.streamapi.collect;
2+
3+
import com.brianway.learning.java8.streamapi.Dish;
4+
import static com.brianway.learning.java8.streamapi.Dish.menu;
5+
import static java.util.stream.Collectors.collectingAndThen;
6+
import static java.util.stream.Collectors.counting;
7+
import static java.util.stream.Collectors.groupingBy;
8+
import static java.util.stream.Collectors.mapping;
9+
import static java.util.stream.Collectors.maxBy;
10+
import static java.util.stream.Collectors.summingInt;
11+
import static java.util.stream.Collectors.toSet;
12+
13+
import java.util.Comparator;
14+
import java.util.List;
15+
import java.util.Map;
16+
import java.util.Optional;
17+
import java.util.Set;
18+
19+
/**
20+
* 分组
21+
*/
22+
public class Grouping {
23+
24+
private enum CaloricLevel {
25+
DIET,
26+
NORMAL,
27+
FAT
28+
}
29+
30+
public static void main(String... args) {
31+
System.out.println("Dishes grouped by type: " + groupDishesByType());
32+
System.out.println("Dishes grouped by caloric level: " + groupDishesByCaloricLevel());
33+
System.out.println("Dishes grouped by type and caloric level: " + groupDishedByTypeAndCaloricLevel());
34+
System.out.println("Count dishes in groups: " + countDishesInGroups());
35+
System.out.println("Most caloric dishes by type: " + mostCaloricDishesByType());
36+
System.out.println("Most caloric dishes by type: " + mostCaloricDishesByTypeWithoutOprionals());
37+
System.out.println("Sum calories by type: " + sumCaloriesByType());
38+
System.out.println("Caloric levels by type: " + caloricLevelsByType());
39+
}
40+
41+
private static CaloricLevel getCaloricLevel(Dish dish) {
42+
if (dish.getCalories() <= 400) {
43+
return CaloricLevel.DIET;
44+
} else if (dish.getCalories() <= 700) {
45+
return CaloricLevel.NORMAL;
46+
} else {
47+
return CaloricLevel.FAT;
48+
}
49+
}
50+
51+
private static Map<Dish.Type, List<Dish>> groupDishesByType() {
52+
return menu.stream().collect(groupingBy(Dish::getType));
53+
}
54+
55+
private static Map<CaloricLevel, List<Dish>> groupDishesByCaloricLevel() {
56+
return menu.stream().collect(
57+
groupingBy(Grouping::getCaloricLevel));
58+
}
59+
60+
/**
61+
* 多级分组
62+
*/
63+
private static Map<Dish.Type, Map<CaloricLevel, List<Dish>>> groupDishedByTypeAndCaloricLevel() {
64+
return menu.stream().collect(
65+
groupingBy(Dish::getType,
66+
groupingBy(Grouping::getCaloricLevel)
67+
)
68+
);
69+
}
70+
71+
/**
72+
* 按子数组收集数据
73+
*/
74+
private static Map<Dish.Type, Long> countDishesInGroups() {
75+
return menu.stream().collect(groupingBy(Dish::getType, counting()));
76+
}
77+
78+
private static Map<Dish.Type, Optional<Dish>> mostCaloricDishesByType() {
79+
return menu.stream().collect(
80+
groupingBy(Dish::getType,
81+
maxBy(Comparator.comparingInt(Dish::getCalories)))
82+
);
83+
}
84+
85+
/**
86+
* 按子数组收集数据,把收集器的结果转换为另一种类型
87+
*/
88+
private static Map<Dish.Type, Dish> mostCaloricDishesByTypeWithoutOprionals() {
89+
return menu.stream().collect(
90+
groupingBy(Dish::getType,
91+
collectingAndThen(
92+
maxBy(Comparator.comparingInt(Dish::getCalories)),
93+
Optional::get)));
94+
}
95+
96+
/**
97+
* 与 groupingBy 联合使用的其他收集器例子
98+
*/
99+
private static Map<Dish.Type, Integer> sumCaloriesByType() {
100+
return menu.stream().collect(groupingBy(Dish::getType,
101+
summingInt(Dish::getCalories)));
102+
}
103+
104+
private static Map<Dish.Type, Set<CaloricLevel>> caloricLevelsByType() {
105+
return menu.stream().collect(
106+
groupingBy(Dish::getType, mapping(
107+
Grouping::getCaloricLevel,
108+
toSet())));
109+
}
110+
}

java8/src/main/java/com/brianway/learning/java8/streamapi/GroupingTransactions.java renamed to java8/src/main/java/com/brianway/learning/java8/streamapi/collect/GroupingTransactions.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.brianway.learning.java8.streamapi;
1+
package com.brianway.learning.java8.streamapi.collect;
22

33
import static java.util.stream.Collectors.groupingBy;
44

java8/src/main/java/com/brianway/learning/java8/streamapi/PartitionPrimeNumbers.java renamed to java8/src/main/java/com/brianway/learning/java8/streamapi/collect/PartitionPrimeNumbers.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.brianway.learning.java8.streamapi;
1+
package com.brianway.learning.java8.streamapi.collect;
22

33
import static java.util.stream.Collector.Characteristics.IDENTITY_FINISH;
44
import static java.util.stream.Collectors.partitioningBy;
@@ -39,6 +39,9 @@ public static Map<Boolean, List<Integer>> partitionPrimes(int n) {
3939
.collect(partitioningBy(PartitionPrimeNumbers::isPrime));
4040
}
4141

42+
/**
43+
* 判断一个数是不是质数
44+
*/
4245
public static boolean isPrime(int candidate) {
4346
return IntStream.rangeClosed(2, candidate - 1)
4447
.limit((long) Math.floor(Math.sqrt((double) candidate)) - 1)
@@ -49,12 +52,22 @@ public static Map<Boolean, List<Integer>> partitionPrimesWithCustomCollector(int
4952
return IntStream.rangeClosed(2, n).boxed().collect(new PrimeNumbersCollector());
5053
}
5154

55+
/**
56+
* 仅用质数作除数
57+
*
58+
* @param primes 部分结果
59+
* @param candidate 要判断的数
60+
* @return
61+
*/
5262
public static boolean isPrime(List<Integer> primes, Integer candidate) {
5363
double candidateRoot = Math.sqrt((double) candidate);
5464
//return primes.stream().filter(p -> p < candidateRoot).noneMatch(p -> candidate % p == 0);
5565
return takeWhile(primes, i -> i <= candidateRoot).stream().noneMatch(i -> candidate % i == 0);
5666
}
5767

68+
/**
69+
* 返回元素满足谓词的最长前缀
70+
*/
5871
public static <A> List<A> takeWhile(List<A> list, Predicate<A> p) {
5972
int i = 0;
6073
for (A item : list) {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.brianway.learning.java8.streamapi.collect;
2+
3+
import com.brianway.learning.java8.streamapi.Dish;
4+
import static com.brianway.learning.java8.streamapi.Dish.menu;
5+
import static java.util.Comparator.comparingInt;
6+
import static java.util.stream.Collectors.collectingAndThen;
7+
import static java.util.stream.Collectors.groupingBy;
8+
import static java.util.stream.Collectors.maxBy;
9+
import static java.util.stream.Collectors.partitioningBy;
10+
11+
import java.util.List;
12+
import java.util.Map;
13+
import java.util.Optional;
14+
15+
/**
16+
* 分区
17+
*/
18+
public class Partitioning {
19+
20+
public static void main(String... args) {
21+
System.out.println("Dishes partitioned by vegetarian: " + partitionByVegeterian());
22+
System.out.println("Vegetarian Dishes by type: " + vegetarianDishesByType());
23+
System.out.println("Most caloric dishes by vegetarian: " + mostCaloricPartitionedByVegetarian());
24+
}
25+
26+
private static Map<Boolean, List<Dish>> partitionByVegeterian() {
27+
return menu.stream().collect(partitioningBy(Dish::isVegetarian));
28+
}
29+
30+
private static Map<Boolean, Map<Dish.Type, List<Dish>>> vegetarianDishesByType() {
31+
return menu.stream().collect(partitioningBy(Dish::isVegetarian, groupingBy(Dish::getType)));
32+
}
33+
34+
private static Object mostCaloricPartitionedByVegetarian() {
35+
return menu.stream().collect(
36+
partitioningBy(Dish::isVegetarian,
37+
collectingAndThen(
38+
maxBy(comparingInt(Dish::getCalories)),
39+
Optional::get)));
40+
}
41+
}
42+

java8/src/main/java/com/brianway/learning/java8/streamapi/Reducing.java renamed to java8/src/main/java/com/brianway/learning/java8/streamapi/collect/Reducing.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
package com.brianway.learning.java8.streamapi;
1+
package com.brianway.learning.java8.streamapi.collect;
22

3+
import com.brianway.learning.java8.streamapi.Dish;
34
import static com.brianway.learning.java8.streamapi.Dish.menu;
45
import static java.util.stream.Collectors.reducing;
56

7+
/**
8+
* 收集器的灵活性,以不同的方法执行相同的操作
9+
*/
610
public class Reducing {
711

812
public static void main(String... args) {
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package com.brianway.learning.java8.streamapi.collect;
2+
3+
import com.brianway.learning.java8.streamapi.Dish;
4+
import static com.brianway.learning.java8.streamapi.Dish.menu;
5+
import static java.util.stream.Collectors.averagingInt;
6+
import static java.util.stream.Collectors.counting;
7+
import static java.util.stream.Collectors.joining;
8+
import static java.util.stream.Collectors.reducing;
9+
import static java.util.stream.Collectors.summarizingInt;
10+
import static java.util.stream.Collectors.summingInt;
11+
12+
import java.util.Comparator;
13+
import java.util.IntSummaryStatistics;
14+
import java.util.function.BinaryOperator;
15+
16+
/**
17+
* 归约和汇总
18+
*/
19+
public class Summarizing {
20+
21+
public static void main(String... args) {
22+
System.out.println("Nr. of dishes: " + howManyDishes());
23+
System.out.println("The most caloric dish is: " + findMostCaloricDish());
24+
System.out.println("The most caloric dish is: " + findMostCaloricDishUsingComparator());
25+
System.out.println("Total calories in menu: " + calculateTotalCalories());
26+
System.out.println("Average calories in menu: " + calculateAverageCalories());
27+
System.out.println("Menu statistics: " + calculateMenuStatistics());
28+
System.out.println("Short menu: " + getShortMenu());
29+
System.out.println("Short menu comma separated: " + getShortMenuCommaSeparated());
30+
}
31+
32+
/**
33+
* 统计个数
34+
*/
35+
private static long howManyDishes() {
36+
return menu.stream().collect(counting());
37+
}
38+
39+
/**
40+
* 查找流中最大值
41+
*/
42+
private static Dish findMostCaloricDish() {
43+
return menu.stream().collect(reducing((d1, d2) -> d1.getCalories() > d2.getCalories() ? d1 : d2)).get();
44+
}
45+
46+
/**
47+
* 查找流中最大值
48+
*/
49+
private static Dish findMostCaloricDishUsingComparator() {
50+
Comparator<Dish> dishCaloriesComparator = Comparator.comparingInt(Dish::getCalories);
51+
BinaryOperator<Dish> moreCaloricOf = BinaryOperator.maxBy(dishCaloriesComparator);
52+
return menu.stream().collect(reducing(moreCaloricOf)).get();
53+
}
54+
55+
/**
56+
* 汇总-求和
57+
*/
58+
private static int calculateTotalCalories() {
59+
return menu.stream().collect(summingInt(Dish::getCalories));
60+
}
61+
62+
/**
63+
* 汇总-求平均数
64+
*/
65+
private static Double calculateAverageCalories() {
66+
return menu.stream().collect(averagingInt(Dish::getCalories));
67+
}
68+
69+
/**
70+
* 汇总-统计值
71+
*/
72+
private static IntSummaryStatistics calculateMenuStatistics() {
73+
return menu.stream().collect(summarizingInt(Dish::getCalories));
74+
}
75+
76+
/**
77+
* 连接字符串
78+
*/
79+
private static String getShortMenu() {
80+
return menu.stream().map(Dish::getName).collect(joining());
81+
}
82+
83+
private static String getShortMenuCommaSeparated() {
84+
return menu.stream().map(Dish::getName).collect(joining(", "));
85+
}
86+
}

0 commit comments

Comments
 (0)