I'm trying to group a data in a list and trying to add a count back to one of the fields of each object of list. Let me put some dummy example here as follows -
public class Book{
String title;
String author;
int count;
}
and there's a list as follows
List<Book> posts = Arrays.asList(
Book.builder().title("Book_1").author("ABC").build(),
Book.builder().title("Book_2").author("PQR").build(),
Book.builder().title("Book_1").author("ABC").build(),
Book.builder().title("Book_3").author("XYZ").build()
);
Now, my objective is to group data in a list by grouping title and author and update the count in count field of Book in list. i.e. in above list as title and author have same values, the count=2 for title="Book_1" and author="ABC", and for other entries count = 1.
I used Apache commons Pair.of() in grouping by as follows -
Map<Pair<String, String>, Long> map = posts.stream()
.collect(Collectors.groupingBy(socialMediaPost -> Pair.of(socialMediaPost.getTitle(), socialMediaPost.getAuthor()), Collectors.counting()));
This actually produces the result but the return type is not what I want. I want List<Book>
back with single entry for duplicate data(title, author) with increased count and other non-duplicate data with count = 1
Maybe you could just use a second stream after your first? something like this where you just extract the books out of the intermediate Pair representation.
Edit: finally, you would just increment everytime you have to combine one, starting with an initial value of 1.
building off your idea, i think something like this would achieve the goal:
List<Book> posts = Arrays.asList(
Book.builder().title("Book_1").author("ABC").build(),
Book.builder().title("Book_2").author("PQR").build(),
Book.builder().title("Book_1").author("ABC").build(),
Book.builder().title("Book_3").author("XYZ").build()
);
List<Book> books = posts.stream()
.collect(Collectors.groupingBy(
socialMediaPost -> {
// initial value of 1
socialMediaPost.setCount(1);
return Pair.of(socialMediaPost.getTitle(),
socialMediaPost.getAuthor());
},
// gets the first of each repeat, incrementing count
Collectors.reducing((a, b) -> a.setCount(a.getCount() + 1))))
.values()
.stream()
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
books.stream().map(Book::toString).forEach(System.out::println);
/*
SO_75775541.Book(title=Book_3, author=XYZ, count=1)
SO_75775541.Book(title=Book_1, author=ABC, count=2)
SO_75775541.Book(title=Book_2, author=PQR, count=1)
*/