2014-11-06 77 views
2

Stream有幾種方法,尤其是當處理可以這樣或那樣寫的數值。 (同樣的問題也適用於average()流收集與地圖收集

那麼哪種方法最好:

DoubleSummaryStatistics result; 

result = stream() 
     .collect(Collectors.summarizingDouble(weighter::weight)); 

result = stream() 
     .mapToDouble(weighter::weight) 
     .summaryStatistics(); 

,爲什麼? (正如我所看到的,第一個優點是「訪問」每個元素只有一次,而第二個有更清晰的語義,但訪問每個元素至少兩次,但這是甚至重要/正確嗎?)

+1

我認爲這是沒有辦法參訪,都是正確的這取決於你想要達到... – BlueLettuce16 2014-11-06 09:08:23

回答

4

在性能方面,似乎第二種方法(圖然後總結)比第一種方法(使用收集器)快:

Benchmark       (n) Mode Samples  Score  Error Units 
c.a.p.SO26775395.collector   10 avgt  10  0.110 ± 0.004 us/op 
c.a.p.SO26775395.collector  1000 avgt  10  9.134 ± 0.310 us/op 
c.a.p.SO26775395.collector 1000000 avgt  10 9091.649 ± 274.113 us/op 
c.a.p.SO26775395.summary   10 avgt  10  0.110 ± 0.003 us/op 
c.a.p.SO26775395.summary   1000 avgt  10  5.593 ± 0.234 us/op 
c.a.p.SO26775395.summary  1000000 avgt  10 5598.776 ± 153.314 us/op 

基準代碼:

@State(Scope.Thread) 
@BenchmarkMode(Mode.AverageTime) 
public class SO26775395 { 

    @Param({"10", "1000", "1000000"}) int n; 
    List<Weighter> weights; 

    @Setup public void setup() { 
    weights = new Random().doubles(n) 
      .mapToObj(Weighter::new) 
      .collect(toList()); 
    } 

    @Benchmark public DoubleSummaryStatistics collector() { 
    return weights.stream().collect(Collectors.summarizingDouble(Weighter::w)); 
    } 

    @Benchmark public DoubleSummaryStatistics summary() { 
    return weights.stream().mapToDouble(Weighter::w).summaryStatistics(); 
    } 

    public static class Weighter { 
    private final double w; 
    public Weighter(double w) { this.w = w; } 
    public double w() { return w; } 
    } 

} 
+0

所以第二個更清潔*和*更快。我想知道爲什麼。基準看起來很有趣。你用了什麼? – Scheintod 2014-11-06 10:32:29

+0

@Scheintod http://openjdk.java.net/projects/code-tools/jmh/ – assylias 2014-11-06 11:34:04

-2

summaryStatistics()給你更多的信息,但其性能可能不是所期望的,取決於你希望得到儘可能輸出什麼...

+1

號他們都給出相同的結果是什麼。 – Scheintod 2014-11-06 09:12:13

1

許多,因爲它們代表了一個流上直接訪問操作預定義Collectors似乎是多餘的。但是,當你開始編寫收集器時,它們是有意義的。例如:

Map<Department, DoubleSummaryStatistics> statsByDept = employees.stream() 
    .collect(Collectors.groupingBy(Employee::getDepartment, 
            Collectors.summarizingDouble(Employee::getSalary)));