Some List is here
List<Book> list = new ArrayList<>();
{
list.add(new Book("Core Java", 200));
list.add(new Book("Core Java", 500));
list.add(new Book("Core Java", 800));
list.add(new Book("Learning Freemarker", 150));
list.add(new Book("Learning Freemarker", 1350));
list.add(new Book("Learning Freemarker", 1250));
list.add(new Book("Spring MVC", 300));
list.add(new Book("Spring MVC", 600));
list.add(new Book("Spring MVC", 1600));
}
I want show Book list like this
Core Java", 800
Learning Freemarker", 1350
Spring MVC", 1600
each 1element
list .stream().distinct()
.sorted(Comparator.comparing(Book::bookname)
.thenComparing(Book::getPrice)).collect(Collectors.toList());
this code only sorted.
First you can do a group by on Book
name and collect them into Map<String, List<Book>>
, And then from map.values()
collect the highest price book from each type
List<Book> books = list.stream()
.collect(Collectors.groupingBy(Book::getName))
.values()
.stream()
.map(book -> Collections.max(book, Comparator.comparingInt(Book::getCost)))
.collect(Collectors.toList());
The other solution suggested by @Holger using Collectors.toMap
will be more effective comparing to collecting and finding the max element
List<Book> books = list.stream()
.collect(Collectors.collectingAndThen(
Collectors.toMap(Book::getName, Function.identity(),
BinaryOperator.maxBy(Comparator.comparingInt(Book::getCost))),
m -> new ArrayList<>(m.values())));
The distinct and then using sorting implies that all distinct books (not just by name) would be selected, further sorting then would still not remove the other entries in the input list until you reduce them somehow. Further based on the desired output, that shouldn't be the way to go.
Instead what you can seek for is using bookName
as an attribute to check for uniqueness and then merging the books comparing their prices and collecting them to our final result.
A fairly simple code to what you're looking forwards to would be using toMap
such as:
List<Book> distinctMaxPriceBooks = new ArrayList<>(list.stream()
.collect(Collectors.toMap(Book::getBookName, Function.identity(),
(b1, b2) -> b1.getPrice() >= b2.getPrice() ? b1 : b2))
.values());
Of course, these can be sorted based on the name if that was anyhow the requirement.
One version that makes use of the max
method and prints sorted results.
list.stream()
.collect(Collectors.groupingBy(Book::getaString))
.values()
.stream()
.map( (books) -> books.stream().max(Comparator.comparingInt(Book::getaNumber)).get())
.sorted(Comparator.comparingInt(Book::getaNumber))
.forEach(System.out::println);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.