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

前端 未结 5 1299
梦如初夏
梦如初夏 2020-12-10 05:45

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         


        
5条回答
  •  无人及你
    2020-12-10 06:31

    By analogy with IntSummaryStatistics, create a class PointStatistics which collects the information you need. It defines two methods: one for recording values from a Point, one for combining two Statistics.

    class PointStatistics {
        private int minX = Integer.MAX_VALUE;
        private int maxX = Integer.MIN_VALUE;
    
        private int minY = Integer.MAX_VALUE;
        private int maxY = Integer.MIN_VALUE;
    
        public void accept(Point p) {
            minX = Math.min(minX, p.x);
            maxX = Math.max(maxX, p.x);
    
            minY = Math.min(minY, p.y);
            maxY = Math.max(minY, p.y);
        }
    
        public void combine(PointStatistics o) {
            minX = Math.min(minX, o.minX);
            maxX = Math.max(maxX, o.maxX);
    
            minY = Math.min(minY, o.minY);
            maxY = Math.max(maxY, o.maxY);
        }
    
        // getters
    }
    

    Then you can collect a Stream into a PointStatistics.

    class Program {
        public static void main(String[] args) {
            List points = new ArrayList<>();
    
            // populate 'points'
    
            PointStatistics statistics = points
                        .stream()
                        .collect(PointStatistics::new, PointStatistics::accept, PointStatistics::combine);
        }
    }
    

    UPDATE

    I was completely baffled by the conclusion drawn by OP, so I decided to write JMH benchmarks.

    Benchmark settings:

    # JMH version: 1.21
    # VM version: JDK 1.8.0_171, Java HotSpot(TM) 64-Bit Server VM, 25.171-b11
    # Warmup: 1 iterations, 10 s each
    # Measurement: 10 iterations, 10 s each
    # Timeout: 10 min per iteration
    # Benchmark mode: Average time, time/op
    

    For each iteration, I was generating a shared list of random Points (new Point(random.nextInt(), random.nextInt())) of size 100K, 1M, 10M.

    The results are

    100K

    Benchmark                        Mode  Cnt  Score   Error  Units
    
    customCollector                  avgt   10  6.760 ± 0.789  ms/op
    forEach                          avgt   10  0.255 ± 0.033  ms/op
    fourStreams                      avgt   10  5.115 ± 1.149  ms/op
    statistics                       avgt   10  0.887 ± 0.114  ms/op
    twoStreams                       avgt   10  2.869 ± 0.567  ms/op
    

    1M

    Benchmark                        Mode  Cnt   Score   Error  Units
    
    customCollector                  avgt   10  68.117 ± 4.822  ms/op
    forEach                          avgt   10   3.939 ± 0.559  ms/op
    fourStreams                      avgt   10  57.800 ± 4.817  ms/op
    statistics                       avgt   10   9.904 ± 1.048  ms/op
    twoStreams                       avgt   10  32.303 ± 2.498  ms/op
    

    10M

    Benchmark                        Mode  Cnt    Score     Error  Units
    
    customCollector                  avgt   10  714.016 ± 151.558  ms/op
    forEach                          avgt   10   54.334 ±   9.820  ms/op
    fourStreams                      avgt   10  699.599 ± 138.332  ms/op
    statistics                       avgt   10  148.649 ±  26.248  ms/op
    twoStreams                       avgt   10  429.050 ±  72.879  ms/op
    

提交回复
热议问题