在Java 8中找到高低

时间:2014-05-19 08:01:11

标签: java list parallel-processing 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;
}

这里是使用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;
}

1 个答案:

答案 0 :(得分:8)

在开始考虑性能之前,您应该考虑正确性。您正在使用 parallel 流以及非线程安全的自定义有状态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;

此外,除非您已将变量HighLowTuple.highHighLowTuple.low声明为volatile,否则当您在没有同步的情况下使用多线程时,JVM的优化可能会导致更多的更新丢失。但是 if 你已声明它们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());

但是,当然,如果你有一组int值,那么使用IntStream代替它会更有效率,而不是绕道而去绕Collection Integer

IntSummaryStatistics s = IntStream.of(array).parallel().summaryStatistics();