Stream - Collect by property and max

前端 未结 3 1028
没有蜡笔的小新
没有蜡笔的小新 2021-01-18 09:15

Problem Statement

Given the following class (simplified for the question):

public static class Match {

  private final String type;
  private fina         


        
3条回答
  •  没有蜡笔的小新
    2021-01-18 10:09

    I have two methods for you.

    First Method: Collectors.toMap()

    A possible implementation is to use Collectors.toMap() to answers your problem.

    stream.collect(Collectors.toMap(Match::getType, Match::getScore, Math::max));
    

    And if you prefer to get a List(), you can remap the result

    stream
        .collect(Collectors.toMap(Match::getType, Match::getScore, Math::max))
        .entrySet()
        .stream()
        .map(e -> new Match(e.getKey(), e.getValue()))
        .collect(Collectors.toList());
    

    Second Method: Custom Collector

    Like you say in your question, it is possible to extract this logic in a custom collector. You can do it like this:

    public class MaxMatch implements Collector, List> {
        @Override
        public Supplier> supplier() {
            return HashMap::new;
        }
    
        @Override
        public BiConsumer, Match> accumulator() {
            return (map, match) -> {
                Integer score = match.getScore();
                if(map.containsKey(match.getType())) {
                    score = Math.max(score, map.get(match.getType()));
                }
                map.put(match.getType(), score);
            };
        }
    
        @Override
        public BinaryOperator> combiner() {
            return (mapA, mapB) -> {
                mapA.forEach((k, v) -> {
                    if(mapB.containsKey(k)) { mapB.put(k, Math.max(v, mapB.get(k))); }
                    else { mapB.put(k, v); }
                });
                return mapB;
            };
        }
    
        @Override
        public Function, List> finisher() {
            return (map) -> map.entrySet().stream().map(e -> new Match(e.getKey(), e.getValue())).collect(Collectors.toList());
        }
    
        @Override
        public Set characteristics() {
            return Collections.emptySet();
        }
    }
    

    and use it like this:

    stream.collect(new MaxMatch());
    

    Hope this help you :)

提交回复
热议问题