Java Stream: find an element with a min/max value of an attribute

后端 未结 9 1768
梦毁少年i
梦毁少年i 2020-12-06 15:58

I have a stream of objects and I would like to find the one with a maximal value of some attribute that\'s expensive to calculate.

As a specific simple example, say

9条回答
  •  天涯浪人
    2020-12-06 16:35

    This is a reduction problem. Reducing a list down to a specific value. In general reduce works down the list operating on a partial solution and an item in the list. In this case, that would mean comparing the previous 'winning' value to the new value from the list which will calculate the expensive operation twice on each comparison.

    According to https://docs.oracle.com/javase/tutorial/collections/streams/reduction.html an alternative is to use collect instead of reduce.

    A custom consumer class will allow keeping track of the expensive operations as it reduces the list. Consumer can get around the multiple calls to the expensive calculation by working with mutable state.

        class Cooler implements Consumer{
    
        String coolestString = "";
        int coolestValue = 0;
    
        public String coolest(){
            return coolestString;
        }
        @Override
        public void accept(String arg0) {
            combine(arg0, expensive(arg0));
        }
    
        private void combine (String other, int exp){
            if (coolestValue < exp){
                coolestString = other;
                coolestValue = exp;
            }
        }
        public void combine(Cooler other){
            combine(other.coolestString, other.coolestValue);
        }
    }
    

    This class accepts a string and if it is cooler than the previous winner, it replaces it and saves the expensive calculated value.

    Cooler cooler =  Stream.of("java", "php", "clojure", "c", "lisp")
                     .collect(Cooler::new, Cooler::accept, Cooler::combine);
    System.out.println(cooler.coolest());
    

提交回复
热议问题