使用Stream从HashSet中排除极值

jpd*_*ond 4 java performance java-8 java-stream

我一直在试验Java 8流,这是删除最小和最大分数的最佳方法.

private final Set<MatchScore> scores = new HashSet<>(10);

. . .

public double OPR() {
    return scores.stream()
            .mapToDouble(MatchScore::getScore)
            .filter((num) -> { //Exclude min and max score
                return num != scores.stream()
                                    .mapToDouble(MatchScore::getScore)
                                    .max().getAsDouble() 
                        && 
                       num != scores.stream()
                                    .mapToDouble(MatchScore::getScore)
                                    .min().getAsDouble();
            })
            .average().getAsDouble();
}
Run Code Online (Sandbox Code Playgroud)

ass*_*ias 8

一种更简单的方法是:

return scores.stream()
        .mapToDouble(MatchScore::getScore)
        .sorted()
        .skip(1)
        .limit(scores.size() - 2)
        .average().getAsDouble();
Run Code Online (Sandbox Code Playgroud)

注意:这是有效的,因为集合中的元素是唯一的 - 列表中可能有多个元素等于最小或最大分数.


性能方面*,跳过/限制在一小组10个元素上显着更快(均值列显示样本调用所花费的平均时间,以纳秒为单位):

Benchmark                      Mode   Samples         Mean   Mean error    Units
c.a.p.SO22923505.maxMin        avgt         5     6996.190      284.287    ns/op
c.a.p.SO22923505.skipLimit     avgt         5      479.935        4.547    ns/op
Run Code Online (Sandbox Code Playgroud)

*使用jmh - 这是测试的源代码.