How to get multiple values from an object using a single stream operation?

  • A+
Category:Languages

I want to determine the minimum area required to display a collection of points. The easy way is to loop through the collection like this:

int minX = Integer.MAX_VALUE; int maxX = Integer.MIN_VALUE; int minY = Integer.MAX_VALUE; int maxY = Integer.MIN_VALUE; for (Point point: points) {     if (point.x < minX) {         minX = point.x;     }     if (point.x > maxX) {         maxX = point.x;     }     if (point.y < minY) {         minY = point.y;     }     if (point.y > maxY) {         maxY = point.y;     } } 

I am getting to know streams. To do the same, you can do the following:

int minX = points.stream().mapToInt(point -> point.x).min().orElse(-1); int maxX = points.stream().mapToInt(point -> point.x).max().orElse(-1); int minY = points.stream().mapToInt(point -> point.y).min().orElse(-1); int maxY = points.stream().mapToInt(point -> point.y).max().orElse(-1); 

Both give the same result. However, although the streams approach is elegant, it is much slower (as expected).

Is there a way to get minX, maxX, minY and maxY in a single stream operation?

 


You could divide by two the iterations with summaryStatistics() while keeping a straight code :

IntSummaryStatistics stat = points.stream().mapToInt(point -> point.x).summaryStatistics(); int minX = stat.getMin(); int maxX = stat.getMax(); 

And do the same thing with point.y.
You could factor out in this way :

Function<ToIntFunction<Point>, IntSummaryStatistics> statFunction =         intExtractor -> points.stream()                               .mapToInt(p -> intExtractor.applyAsInt(pp))                               .summaryStatistics();  IntSummaryStatistics statX = statFunction.apply(p -> p.x); IntSummaryStatistics statY = statFunction.apply(p -> p.y); 

A custom collector is a possibility but note that you should implement the combiner part that will not require additional processing that will make your code harder to read.

So but if you need to use parallel stream you should stay to the imperative way.
While you could improve your actual code by relying the Math.min and Math.max functions :

for (Point p : points) {     minX = Math.min(p.x, minX);     minY = Math.min(p.y, minY);     maxY = Math.max(p.x, maxX);     maxY = Math.max(p.y, maxY); } 

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: