Skip to content

Commit f0e835b

Browse files
authored
Bael 5066 aggregate over multiple fields (eugenp#11156)
* Commit source code to branch * BAEL-5065 improvement of groupBy with complex key * Aggregation of multiple attributes of a grouped result
1 parent 4039208 commit f0e835b

2 files changed

Lines changed: 61 additions & 8 deletions

File tree

core-java-modules/core-java-16/src/main/java/com/baeldung/java_16_features/groupingby/BlogPost.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
package com.baeldung.java_16_features.groupingby;
22

3+
import java.util.IntSummaryStatistics;
4+
5+
36
public class BlogPost {
47

58
private String title;
69
private String author;
710
private BlogPostType type;
811
private int likes;
912
record AuthPostTypesLikes(String author, BlogPostType type, int likes) {};
10-
13+
record PostcountTitlesLikesStats(long postCount, String titles, IntSummaryStatistics likesStats){};
14+
record TitlesBoundedSumOfLikes(String titles, int boundedSumOfLikes) {};
15+
1116
public BlogPost(String title, String author, BlogPostType type, int likes) {
1217
this.title = title;
1318
this.author = author;

core-java-modules/core-java-16/src/test/java/com/baeldung/java_16_features/groupingby/JavaGroupingByCollectorUnitTest.java

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import static java.util.stream.Collectors.counting;
66
import static java.util.stream.Collectors.groupingBy;
77
import static java.util.stream.Collectors.groupingByConcurrent;
8+
import static java.util.stream.Collectors.collectingAndThen;
9+
import static java.util.stream.Collectors.toMap;
810
import static java.util.stream.Collectors.joining;
911
import static java.util.stream.Collectors.mapping;
1012
import static java.util.stream.Collectors.maxBy;
@@ -13,6 +15,7 @@
1315
import static java.util.stream.Collectors.toList;
1416
import static java.util.stream.Collectors.toSet;
1517
import static org.assertj.core.api.Assertions.assertThat;
18+
import static org.assertj.core.api.Assertions.offset;
1619
import static org.junit.jupiter.api.Assertions.assertEquals;
1720
import static org.junit.jupiter.api.Assertions.assertNull;
1821
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -201,9 +204,9 @@ public void givenAListOfPosts_whenGroupedByTypeAndSummarizingLikes_thenGetAMapBe
201204

202205
@Test
203206
public void givenAListOfPosts_whenGroupedByComplexMapPairKeyType_thenGetAMapBetweenPairAndList() {
204-
207+
205208
Map<Pair<BlogPostType, String>, List<BlogPost>> postsPerTypeAndAuthor = posts.stream()
206-
.collect(groupingBy(post -> new ImmutablePair<>(post.getType(), post.getAuthor())));
209+
.collect(groupingBy(post -> new ImmutablePair<>(post.getType(), post.getAuthor())));
207210

208211
List<BlogPost> result = postsPerTypeAndAuthor.get(new ImmutablePair<>(BlogPostType.GUIDE, "Author 1"));
209212

@@ -218,7 +221,7 @@ public void givenAListOfPosts_whenGroupedByComplexMapPairKeyType_thenGetAMapBetw
218221

219222
@Test
220223
public void givenAListOfPosts_whenGroupedByComplexMapKeyType_thenGetAMapBetweenTupleAndList() {
221-
224+
222225
Map<Tuple, List<BlogPost>> postsPerTypeAndAuthor = posts.stream()
223226
.collect(groupingBy(post -> new Tuple(post.getType(), post.getAuthor())));
224227

@@ -232,12 +235,12 @@ public void givenAListOfPosts_whenGroupedByComplexMapKeyType_thenGetAMapBetweenT
232235
assertThat(blogPost.getType()).isEqualTo(BlogPostType.GUIDE);
233236
assertThat(blogPost.getAuthor()).isEqualTo("Author 1");
234237
}
235-
238+
236239
@Test
237240
public void givenAListOfPosts_whenGroupedByRecord_thenGetAMapBetweenRecordAndList() {
238-
241+
239242
Map<BlogPost.AuthPostTypesLikes, List<BlogPost>> postsPerTypeAndAuthor = posts.stream()
240-
.collect(groupingBy(post -> new BlogPost.AuthPostTypesLikes(post.getAuthor(), post.getType(), post.getLikes())));
243+
.collect(groupingBy(post -> new BlogPost.AuthPostTypesLikes(post.getAuthor(), post.getType(), post.getLikes())));
241244

242245
List<BlogPost> result = postsPerTypeAndAuthor.get(new BlogPost.AuthPostTypesLikes("Author 1", BlogPostType.GUIDE, 20));
243246

@@ -250,5 +253,50 @@ public void givenAListOfPosts_whenGroupedByRecord_thenGetAMapBetweenRecordAndLis
250253
assertThat(blogPost.getAuthor()).isEqualTo("Author 1");
251254
assertThat(blogPost.getLikes()).isEqualTo(20);
252255
}
253-
256+
257+
@Test
258+
public void givenListOfPosts_whenGroupedByAuthor_thenGetAMapUsingCollectingAndThen() {
259+
260+
Map<String, BlogPost.PostcountTitlesLikesStats> postsPerAuthor = posts.stream()
261+
.collect(groupingBy(BlogPost::getAuthor, collectingAndThen(toList(), list -> {
262+
long count = list.stream()
263+
.map(BlogPost::getTitle)
264+
.collect(counting());
265+
String titles = list.stream()
266+
.map(BlogPost::getTitle)
267+
.collect(joining(" : "));
268+
IntSummaryStatistics summary = list.stream()
269+
.collect(summarizingInt(BlogPost::getLikes));
270+
return new BlogPost.PostcountTitlesLikesStats(count, titles, summary);
271+
})));
272+
273+
BlogPost.PostcountTitlesLikesStats result = postsPerAuthor.get("Author 1");
274+
assertThat(result.postCount()).isEqualTo(3L);
275+
assertThat(result.titles()).isEqualTo("News item 1 : Programming guide : Tech review 2");
276+
assertThat(result.likesStats().getMax()).isEqualTo(20);
277+
assertThat(result.likesStats().getMin()).isEqualTo(15);
278+
assertThat(result.likesStats().getAverage()).isEqualTo(16.666d, offset(0.001d));
279+
}
280+
281+
@Test
282+
public void givenListOfPosts_whenGroupedByAuthor_thenGetAMapUsingToMap() {
283+
284+
int maxValLikes = 17;
285+
Map<String, BlogPost.TitlesBoundedSumOfLikes> postsPerAuthor = posts.stream()
286+
.collect(toMap(BlogPost::getAuthor, post -> {
287+
int likes = (post.getLikes() > maxValLikes) ? maxValLikes : post.getLikes();
288+
return new BlogPost.TitlesBoundedSumOfLikes(post.getTitle(), likes);
289+
}, (u1, u2) -> {
290+
int likes = (u2.boundedSumOfLikes() > maxValLikes) ? maxValLikes : u2.boundedSumOfLikes();
291+
return new BlogPost.TitlesBoundedSumOfLikes(u1.titles()
292+
.toUpperCase() + " : "
293+
+ u2.titles()
294+
.toUpperCase(),
295+
u1.boundedSumOfLikes() + likes);
296+
}));
297+
298+
BlogPost.TitlesBoundedSumOfLikes result = postsPerAuthor.get("Author 1");
299+
assertThat(result.titles()).isEqualTo("NEWS ITEM 1 : PROGRAMMING GUIDE : TECH REVIEW 2");
300+
assertThat(result.boundedSumOfLikes()).isEqualTo(47);
301+
}
254302
}

0 commit comments

Comments
 (0)