Java 8流过滤器对收集方法的优化程度如何?

try*_*arn 4 java collections lambda java-8

例如,我有一个逗号分隔的字符串:

String multiWordString= "... , ... , ... ";
Run Code Online (Sandbox Code Playgroud)

我想检查csv字符串中是否存在另一个字符串str.然后我可以做两件事:

1.

boolean contains = Arrays.asList(multiWordString.split(",")).contains(str);
Run Code Online (Sandbox Code Playgroud)

2.

boolean contains = Arrays.asList(multiWordString.split(",")).stream().filter(e -> e.equals(str)).findFirst();
Run Code Online (Sandbox Code Playgroud)

编辑:示例字符串碰巧使用逗号作为分隔符.我应该使用更好的名称作为样本字符串,以避免混淆.我更新了名字.在这个问题中,我试图找到使用Java 8流和循环/收集方法之间的性能差异.

Eug*_*ene 6

没有测试就无法分辨,内部细节可以改变另一个解决方案的行为,所以最好的方法是衡量.据了解,流有点慢 - 他们背后有基础设施......

这是一个天真的简单测试(数据很少):

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)
@State(Scope.Benchmark)
public class CSVParsing {
    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder().include(CSVParsing.class.getSimpleName())
                .jvmArgs("-ea")
                .shouldFailOnError(true)
                .build();
        new Runner(opt).run();
    }

    @Param(value = { "a,e, b,c,d",
            "a,b,c,d, a,b,c,da,b,c,da,b,c,da,b,c,da,b,c,da,b,c,da,b,c,da,b,c,d, e",
            "r, m, n, t,r, m, n, tr, m, n, tr, m, n, tr, m, n, tr, m, n, tr, m, n, tr, m, n, t, e" })
    String csv;

    @Fork(1)
    @Benchmark
    public boolean containsSimple() {
        return Arrays.asList(csv.split(",")).contains("e");
    }

    @Fork(1)
    @Benchmark
    public boolean containsStream() {
        return Arrays.asList(csv.split(",")).stream().filter(e -> e.equals("e")).findFirst().isPresent();
    }

    @Fork(1)
    @Benchmark
    public boolean containsStreamParallel() {
        return Arrays.asList(csv.split(",")).stream().filter(e -> e.equals("e")).findFirst().isPresent();
    }
}
Run Code Online (Sandbox Code Playgroud)

即使您不理解代码,结果也是可以比较的简单数字:

 CSVParsing.containsSimple   (first Parameter)    181.201 ±   5.390
 CSVParsing.containsStream                        255.851 ±   5.598
 CSVParsing.containsStreamParallel                295.296 ±  57.800
Run Code Online (Sandbox Code Playgroud)

我不打算显示其余结果(对于其他参数),因为它们在相同的范围内.

底线是它们确实不同,最多100 ns ; 让我重复一遍:纳秒.

确实存在差异; 但是,如果你真的很关心这种差异,那么csv解析可能首先是错误的选择.

  • 当然,这些成本都包含在所有这些成本中.但只要您不知道这些基本成本与您所比较的成本之间的比例,结果就毫无意义.可能是`containsSimple`和`containsStream`之间的比例确实大致为'181:255`,但基本成本也可能是'180`,而`containsSimple`和`containsStream`之间的比例是1 :75`.谁知道? (3认同)
  • 准备会引入不同类型的基本代价,另一方面,它不仅跳过数组创建,它只会匹配在链接`filter`操作中查找匹配字符串所需的`,`. `findFirst`.对于包含匹配的大字符串,这可以获得巨大回报.由于总结果取决于输入,因此添加另一个单独的测试将非常有用. (2认同)