Bael 5066 aggregate over multiple fields (#11156)
* Commit source code to branch * BAEL-5065 improvement of groupBy with complex key * Aggregation of multiple attributes of a grouped result
This commit is contained in:
parent
b180037cdc
commit
70283b1191
|
@ -1,5 +1,8 @@
|
||||||
package com.baeldung.java_16_features.groupingby;
|
package com.baeldung.java_16_features.groupingby;
|
||||||
|
|
||||||
|
import java.util.IntSummaryStatistics;
|
||||||
|
|
||||||
|
|
||||||
public class BlogPost {
|
public class BlogPost {
|
||||||
|
|
||||||
private String title;
|
private String title;
|
||||||
|
@ -7,7 +10,9 @@ public class BlogPost {
|
||||||
private BlogPostType type;
|
private BlogPostType type;
|
||||||
private int likes;
|
private int likes;
|
||||||
record AuthPostTypesLikes(String author, BlogPostType type, int likes) {};
|
record AuthPostTypesLikes(String author, BlogPostType type, int likes) {};
|
||||||
|
record PostcountTitlesLikesStats(long postCount, String titles, IntSummaryStatistics likesStats){};
|
||||||
|
record TitlesBoundedSumOfLikes(String titles, int boundedSumOfLikes) {};
|
||||||
|
|
||||||
public BlogPost(String title, String author, BlogPostType type, int likes) {
|
public BlogPost(String title, String author, BlogPostType type, int likes) {
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.author = author;
|
this.author = author;
|
||||||
|
|
|
@ -5,6 +5,8 @@ import static java.util.stream.Collectors.averagingInt;
|
||||||
import static java.util.stream.Collectors.counting;
|
import static java.util.stream.Collectors.counting;
|
||||||
import static java.util.stream.Collectors.groupingBy;
|
import static java.util.stream.Collectors.groupingBy;
|
||||||
import static java.util.stream.Collectors.groupingByConcurrent;
|
import static java.util.stream.Collectors.groupingByConcurrent;
|
||||||
|
import static java.util.stream.Collectors.collectingAndThen;
|
||||||
|
import static java.util.stream.Collectors.toMap;
|
||||||
import static java.util.stream.Collectors.joining;
|
import static java.util.stream.Collectors.joining;
|
||||||
import static java.util.stream.Collectors.mapping;
|
import static java.util.stream.Collectors.mapping;
|
||||||
import static java.util.stream.Collectors.maxBy;
|
import static java.util.stream.Collectors.maxBy;
|
||||||
|
@ -13,6 +15,7 @@ import static java.util.stream.Collectors.summingInt;
|
||||||
import static java.util.stream.Collectors.toList;
|
import static java.util.stream.Collectors.toList;
|
||||||
import static java.util.stream.Collectors.toSet;
|
import static java.util.stream.Collectors.toSet;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.offset;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
@ -201,9 +204,9 @@ public class JavaGroupingByCollectorUnitTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenAListOfPosts_whenGroupedByComplexMapPairKeyType_thenGetAMapBetweenPairAndList() {
|
public void givenAListOfPosts_whenGroupedByComplexMapPairKeyType_thenGetAMapBetweenPairAndList() {
|
||||||
|
|
||||||
Map<Pair<BlogPostType, String>, List<BlogPost>> postsPerTypeAndAuthor = posts.stream()
|
Map<Pair<BlogPostType, String>, List<BlogPost>> postsPerTypeAndAuthor = posts.stream()
|
||||||
.collect(groupingBy(post -> new ImmutablePair<>(post.getType(), post.getAuthor())));
|
.collect(groupingBy(post -> new ImmutablePair<>(post.getType(), post.getAuthor())));
|
||||||
|
|
||||||
List<BlogPost> result = postsPerTypeAndAuthor.get(new ImmutablePair<>(BlogPostType.GUIDE, "Author 1"));
|
List<BlogPost> result = postsPerTypeAndAuthor.get(new ImmutablePair<>(BlogPostType.GUIDE, "Author 1"));
|
||||||
|
|
||||||
|
@ -218,7 +221,7 @@ public class JavaGroupingByCollectorUnitTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenAListOfPosts_whenGroupedByComplexMapKeyType_thenGetAMapBetweenTupleAndList() {
|
public void givenAListOfPosts_whenGroupedByComplexMapKeyType_thenGetAMapBetweenTupleAndList() {
|
||||||
|
|
||||||
Map<Tuple, List<BlogPost>> postsPerTypeAndAuthor = posts.stream()
|
Map<Tuple, List<BlogPost>> postsPerTypeAndAuthor = posts.stream()
|
||||||
.collect(groupingBy(post -> new Tuple(post.getType(), post.getAuthor())));
|
.collect(groupingBy(post -> new Tuple(post.getType(), post.getAuthor())));
|
||||||
|
|
||||||
|
@ -232,12 +235,12 @@ public class JavaGroupingByCollectorUnitTest {
|
||||||
assertThat(blogPost.getType()).isEqualTo(BlogPostType.GUIDE);
|
assertThat(blogPost.getType()).isEqualTo(BlogPostType.GUIDE);
|
||||||
assertThat(blogPost.getAuthor()).isEqualTo("Author 1");
|
assertThat(blogPost.getAuthor()).isEqualTo("Author 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenAListOfPosts_whenGroupedByRecord_thenGetAMapBetweenRecordAndList() {
|
public void givenAListOfPosts_whenGroupedByRecord_thenGetAMapBetweenRecordAndList() {
|
||||||
|
|
||||||
Map<BlogPost.AuthPostTypesLikes, List<BlogPost>> postsPerTypeAndAuthor = posts.stream()
|
Map<BlogPost.AuthPostTypesLikes, List<BlogPost>> postsPerTypeAndAuthor = posts.stream()
|
||||||
.collect(groupingBy(post -> new BlogPost.AuthPostTypesLikes(post.getAuthor(), post.getType(), post.getLikes())));
|
.collect(groupingBy(post -> new BlogPost.AuthPostTypesLikes(post.getAuthor(), post.getType(), post.getLikes())));
|
||||||
|
|
||||||
List<BlogPost> result = postsPerTypeAndAuthor.get(new BlogPost.AuthPostTypesLikes("Author 1", BlogPostType.GUIDE, 20));
|
List<BlogPost> result = postsPerTypeAndAuthor.get(new BlogPost.AuthPostTypesLikes("Author 1", BlogPostType.GUIDE, 20));
|
||||||
|
|
||||||
|
@ -250,5 +253,50 @@ public class JavaGroupingByCollectorUnitTest {
|
||||||
assertThat(blogPost.getAuthor()).isEqualTo("Author 1");
|
assertThat(blogPost.getAuthor()).isEqualTo("Author 1");
|
||||||
assertThat(blogPost.getLikes()).isEqualTo(20);
|
assertThat(blogPost.getLikes()).isEqualTo(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenListOfPosts_whenGroupedByAuthor_thenGetAMapUsingCollectingAndThen() {
|
||||||
|
|
||||||
|
Map<String, BlogPost.PostcountTitlesLikesStats> postsPerAuthor = posts.stream()
|
||||||
|
.collect(groupingBy(BlogPost::getAuthor, collectingAndThen(toList(), list -> {
|
||||||
|
long count = list.stream()
|
||||||
|
.map(BlogPost::getTitle)
|
||||||
|
.collect(counting());
|
||||||
|
String titles = list.stream()
|
||||||
|
.map(BlogPost::getTitle)
|
||||||
|
.collect(joining(" : "));
|
||||||
|
IntSummaryStatistics summary = list.stream()
|
||||||
|
.collect(summarizingInt(BlogPost::getLikes));
|
||||||
|
return new BlogPost.PostcountTitlesLikesStats(count, titles, summary);
|
||||||
|
})));
|
||||||
|
|
||||||
|
BlogPost.PostcountTitlesLikesStats result = postsPerAuthor.get("Author 1");
|
||||||
|
assertThat(result.postCount()).isEqualTo(3L);
|
||||||
|
assertThat(result.titles()).isEqualTo("News item 1 : Programming guide : Tech review 2");
|
||||||
|
assertThat(result.likesStats().getMax()).isEqualTo(20);
|
||||||
|
assertThat(result.likesStats().getMin()).isEqualTo(15);
|
||||||
|
assertThat(result.likesStats().getAverage()).isEqualTo(16.666d, offset(0.001d));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenListOfPosts_whenGroupedByAuthor_thenGetAMapUsingToMap() {
|
||||||
|
|
||||||
|
int maxValLikes = 17;
|
||||||
|
Map<String, BlogPost.TitlesBoundedSumOfLikes> postsPerAuthor = posts.stream()
|
||||||
|
.collect(toMap(BlogPost::getAuthor, post -> {
|
||||||
|
int likes = (post.getLikes() > maxValLikes) ? maxValLikes : post.getLikes();
|
||||||
|
return new BlogPost.TitlesBoundedSumOfLikes(post.getTitle(), likes);
|
||||||
|
}, (u1, u2) -> {
|
||||||
|
int likes = (u2.boundedSumOfLikes() > maxValLikes) ? maxValLikes : u2.boundedSumOfLikes();
|
||||||
|
return new BlogPost.TitlesBoundedSumOfLikes(u1.titles()
|
||||||
|
.toUpperCase() + " : "
|
||||||
|
+ u2.titles()
|
||||||
|
.toUpperCase(),
|
||||||
|
u1.boundedSumOfLikes() + likes);
|
||||||
|
}));
|
||||||
|
|
||||||
|
BlogPost.TitlesBoundedSumOfLikes result = postsPerAuthor.get("Author 1");
|
||||||
|
assertThat(result.titles()).isEqualTo("NEWS ITEM 1 : PROGRAMMING GUIDE : TECH REVIEW 2");
|
||||||
|
assertThat(result.boundedSumOfLikes()).isEqualTo(47);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue