java 8 stream collect max object and distinct by Property

user3066285 :

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.

Deadpool :

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())));

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=11578&siteId=1