2

I've to extract two values ( min & max ) from a List of my custom objects, and currently I am creating streams twice and extracting it separately. I think it might be optimization to use a single stream and use the map or similar function to get both min and max in a single stream. Is that feasible?

public class MyClass {

    public static class MyC {
        double val;
        public MyC(double val) {
            this.val = val;
        }

        public double getVal() {return val;}
    }

    public static void main(String[] args) {


        List<MyC> list = new ArrayList<>();
        list.add(new MyC(10.0d));
        list.add(new MyC(20.0d));

        double min = Optional.ofNullable(list).stream()
                        .flatMap(List::stream)
                        .limit(13)
                        .map(MyC::getVal)
                        .min(Double::compare)
                        .orElse(getMinDefault());

        double max = Optional.ofNullable(list).stream()
                .flatMap(List::stream)
                .limit(13)
                .map(MyC::getVal)
                .max(Double::compare)
                .orElse(getMaxDefault());

    }

    private static double getMinDefault() {
        return 1.0d;
    }

    private static double getMaxDefault() {
        return 20.0d;
    }
}
Naman
  • 27,789
  • 26
  • 218
  • 353
Novice User
  • 3,552
  • 6
  • 31
  • 56

1 Answers1

3

You can use DoubleSummaryStatistics for both the max and min of your value attribute.

DoubleSummaryStatistics summaryStatistics = list // avoid initialising list as 'null'
        .stream()
        .limit(13)
        .mapToDouble(MyC::getVal)
        .summaryStatistics();
double max = summaryStatistics.getMax();
double min = summaryStatistics.getMin();

Regarding the custom default values to fall back upon, you can use conditional logic such as :

double max = getMaxDefault();
double min = getMinDefault();
if (!list.isEmpty()) {
    DoubleSummaryStatistics summaryStatistics = list
            .stream()
            .limit(13)
            .mapToDouble(MyC::getVal)
            .summaryStatistics();

    max = summaryStatistics.getMax();
    min = summaryStatistics.getMin();
}
Naman
  • 27,789
  • 26
  • 218
  • 353
  • This is pretty close, but if you see my response, `orElse` has different defaults for max and min, how can i do similar here? – Novice User Oct 15 '19 at 02:28
  • 1
    @NoviceUser updated in the answer, it would be better handled as a conditional branch rather than the use of `Optional` here. – Naman Oct 15 '19 at 02:33