在Java 8中找到高潮和低潮 - java

我正在测试以各种方式在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;
}

参考方案

在开始考虑性能之前,您应该考虑正确性。您正在将并行流与非线程安全的自定义有状态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的优化可能会导致更多更新丢失。但是,如果已将它们声明为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而不是绕开CollectionInteger效率会更高:

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

在Java Swing中输入JButton的键焦点? - java

如何在Java Swing中使JButton的Enter键成为焦点?我已经这样做了btn_Login.registerKeyboardAction(new ActionListener() { public void actionPerformed(ActionEvent e) { System.out.println("enter key pre…

在Java 8中,为什么ArrayList的默认容量现在为零? - java

我记得,在Java 8之前,ArrayList的默认容量为10。出乎意料的是,对默认(无效)构造函数的评论仍然显示:Constructs an empty list with an initial capacity of ten.来自ArrayList.java:/** * Shared empty array instance used for defau…

在Java 8流中,如何过滤掉不是枚举有效值的字符串? - java

我有一个枚举,我称之为对我的应用程序重要的安全权限的Permission。在数据库中,用户可能具有与我的应用程序无关的其他权限。从数据库中读取用户时,我得到一个List<String>,并且我想建立一个List<Permission>,而忽略了那些不是枚举值的字符串。public enum Permission { ADMIN, US…

Java:线程池如何将线程映射到可运行对象 - java

试图绕过Java并发问题,并且很难理解线程池,线程以及它们正在执行的可运行“任务”之间的关系。如果我创建一个有10个线程的线程池,那么我是否必须将相同的任务传递给池中的每个线程,或者池化的线程实际上只是与任务无关的“工人无人机”可用于执行任何任务?无论哪种方式,Executor / ExecutorService如何将正确的任务分配给正确的线程? 参考方案 …

JAVA:字节码和二进制有什么区别? - java

java字节代码(已编译的语言,也称为目标代码)与机器代码(当前计算机的本机代码)之间有什么区别?我读过一些书,他们将字节码称为二进制指令,但我不知道为什么。 参考方案 字节码是独立于平台的,在Windows中运行的编译器编译的字节码仍将在linux / unix / mac中运行。机器代码是特定于平台的,如果在Windows x86中编译,则它将仅在Win…