在Java 8中找到高低

dan*_*iza 2 java parallel-processing list java-8 java-stream

我正在测试在Java中的列表中搜索低值和高值的不同方法,我意识到使用stream()和parallelStream()方法的结果更慢且性能更差,而不仅仅是遍历列表......

这可能吗?这怎么可能?

这是我的代码:

迭代整个数组:

    private HighLowTuple calculateIteratingWholeArray( List<Integer> arrayWithNumbers,         int from, int to )
        {

    // long start = System.currentTimeMillis();
    HighLowTuple result = new HighLowTuple( -1, Integer.MAX_VALUE );
    for( int i = from; i < to; i++ )
    {

        int value = arrayWithNumbers.get( i );

        if( value > result.high )
        {
            result.high = value;
        }

        if( value < result.low )
        {
            result.low = value;
        }

    }
    // long end = System.currentTimeMillis();
    // System.out.println( "duration internal calculateIteratingWholeArray from " + from +
    // " to + " + to + "  "
    // + ( end - start ) + " ms" );
    return result;
}
Run Code Online (Sandbox Code Playgroud)

这里使用java 8流的代码:

     private HighLowTuple calculateUsingStreamParallel( List<Integer> arrayWithIntegers )
{
    HighLowTuple result = new HighLowTuple( -1, Integer.MAX_VALUE );

    Consumer<Integer> highlow = new Consumer<Integer>()
    {

        @Override
        public void accept( Integer number )
        {
            if( result.high < number )
                result.high = number;

            if( result.low > number )
                result.low = number;

        }
    };
    arrayWithIntegers.stream().parallel().forEach( highlow );
    return result;
}
Run Code Online (Sandbox Code Playgroud)

Hol*_*ger 8

在开始考虑性能之前,您应该考虑正确性.您正在使用具有非线程安全的自定义有状态的并行Consumer:

if( result.high < number )
// if another thread updates ?high? right at this point you might loose a value
    result.high = number;

if( result.low > number )
// again, possible loss of values here
    result.low = number;
Run Code Online (Sandbox Code Playgroud)

此外,除非您已声明变量HighLowTuple.high,HighLowTuple.low因此volatile,当您在没有同步的情况下使用多线程时,JVM的优化可能会导致更多的更新丢失.但是如果你已经声明它们,volatile你不应该对性能降低感到惊讶(虽然代码不正确).


解决方案是首先了解API.你已经重新发明了这个轮子,因为已经有一种简洁的方法可以在Java 8中找到高低:

IntSummaryStatistics s = arrayWithIntegers.stream()
  .parallel().mapToInt(Integer::intValue).summaryStatistics();
// if you still like your tuple class:
return new HighLowTuple(s.getMax(), s.getMin());
Run Code Online (Sandbox Code Playgroud)

但是,当然,如果你有一个数组int值,将会变得更有效地使用一个IntStream出来的,而不是使搁着的CollectionInteger:

IntSummaryStatistics s = IntStream.of(array).parallel().summaryStatistics();
Run Code Online (Sandbox Code Playgroud)