Arrays.asList与Arrays.stream一起使用forEach()

时间:2014-12-09 23:50:15

标签: java lambda java-8 java-stream

如果你有一个数组而你想使用Java8 forEach()方法,那么哪种方法更好或更有效:

Arrays.asList(new String[]{"hallo","hi"}).forEach(System.out::println);

Arrays.stream(new String[]{"hallo","hi"}).forEach(System.out::println);

差异是显着的还是有更好的解决方案来解决这个问题?

3 个答案:

答案 0 :(得分:16)

都不是。如果你已经有一个数组,

String[] array;

我会用:

Arrays.stream(array).forEach(System.out::println);

因为您将数组的转换保留为JDK的流 - 让它负责效率等。

但是,由于您没有数组,我会使用Stream.of()的varargs来创建值的流:

Stream.of("hallo","hi").forEach(System.out::println);

这再次让JDK负责在其认为合适时有效地传输值。

答案 1 :(得分:6)

它似乎几乎完全没有区别。我为此创建了一个测试类。在五次运行过程中,我的输出是:

Run 1:
Arrays.asList() method................: 3231 ms
Arrays.stream() method................: 3111 ms
Stream.of() method....................: 3031 ms
Arrays.asList() (premade array) method: 3086 ms
Arrays.stream() (premade array) method: 3231 ms
Stream.of() (premade array) method....: 3191 ms

Run 2:
Arrays.asList() method................: 3270 ms
Arrays.stream() method................: 3072 ms
Stream.of() method....................: 3086 ms
Arrays.asList() (premade array) method: 3002 ms
Arrays.stream() (premade array) method: 3251 ms
Stream.of() (premade array) method....: 3271 ms

Run 3:
Arrays.asList() method................: 3307 ms
Arrays.stream() method................: 3092 ms
Stream.of() method....................: 2911 ms
Arrays.asList() (premade array) method: 3035 ms
Arrays.stream() (premade array) method: 3241 ms
Stream.of() (premade array) method....: 3241 ms

Run 4:
Arrays.asList() method................: 3630 ms
Arrays.stream() method................: 2981 ms
Stream.of() method....................: 2821 ms
Arrays.asList() (premade array) method: 3058 ms
Arrays.stream() (premade array) method: 3221 ms
Stream.of() (premade array) method....: 3214 ms

Run 5:
Arrays.asList() method................: 3338 ms
Arrays.stream() method................: 3174 ms
Stream.of() method....................: 3262 ms
Arrays.asList() (premade array) method: 3064 ms
Arrays.stream() (premade array) method: 3269 ms
Stream.of() (premade array) method....: 3275 ms

从输出中看,Stream.of()方法看起来非常有效(但始终如一)是最有效的,

Stream.of("hallo","hi").forEach(System.out::println);

是非常易读的代码。 Stream.of的优点在于它不必将数组转换为列表,或创建数组然后创建流,但可以直接从元素创建流。对我来说有点令人惊讶的是,由于我进行测试的方式,每次使用Stream.of()实例化一个新的数组流比通过一个预先制作的数组更快,可能是因为“捕获“lambdas - 引用外部变量的那些 - 效率稍差。

以下是我的测试类的代码:

import java.util.Arrays;
import java.util.function.Consumer;
import java.util.stream.Stream;


public class StreamArrayTest {

    public static void main(String[] args){
        System.out.println("Arrays.asList() method................: " + arraysAsListMethod() + " ms");
        System.out.println("Arrays.stream() method................: " + arraysStreamMethod() + " ms");
        System.out.println("Stream.of() method....................: " + streamOfMethod() + " ms");
        System.out.println("Arrays.asList() (premade array) method: " + presetArraysAsListMethod() + " ms");
        System.out.println("Arrays.stream() (premade array) method: " + presetArraysStreamMethod() + " ms");
        System.out.println("Stream.of() (premade array) method....: " + presetStreamsOfMethod() + " ms");
    }

    private static Long timeOneMillion(Runnable runner){
        MilliTimer mt = MilliTimer.start();
        for (int i = 0; i < 1000000; i++){
            runner.run();
        }
        return mt.end();
    }

    private static Long timeOneMillion(String[] strings, Consumer<String[]> consumer){
        MilliTimer mt = MilliTimer.start();
        for (int i = 0; i < 1000000; i++){
            consumer.accept(strings);
        }
        return mt.end();        
    }

    public static Long arraysAsListMethod(){
        return timeOneMillion(()->Arrays.asList(new String[]{"hallo","hi","test","test2","test3","test4","test5","test6","test7","test8"}).forEach(StreamArrayTest::doSomething));
    }

    public static Long arraysStreamMethod(){
        return timeOneMillion(()->Arrays.stream(new String[]{"hallo","hi","test","test2","test3","test4","test5","test6","test7","test8"}).forEach(StreamArrayTest::doSomething));
    }

    public static Long streamOfMethod(){
        return timeOneMillion(()->Stream.of("hallo","hi","test","test2","test3","test4","test5","test6","test7","test8").forEach(StreamArrayTest::doSomething));        
    }   

    public static Long presetArraysAsListMethod(){
        String[] strings = new String[]{"hallo","hi","test","test2","test3","test4","test5","test6","test7","test8"};
        return timeOneMillion(strings, (s)->Arrays.asList(s).forEach(StreamArrayTest::doSomething));    
    }

    public static Long presetArraysStreamMethod(){
        String[] strings = new String[]{"hallo","hi","test","test2","test3","test4","test5","test6","test7","test8"};
        return timeOneMillion(strings, (s)->Arrays.stream(s).forEach(StreamArrayTest::doSomething));    
    }

    public static Long presetStreamsOfMethod(){
        String[] strings = new String[]{"hallo","hi","test","test2","test3","test4","test5","test6","test7","test8"};
        return timeOneMillion(strings, (s)->Stream.of(s).forEach(StreamArrayTest::doSomething));    
    }

    public static void doSomething(String s){
        String result = s;
        for (int i = 0; i < 10; i++){
            result = result.concat(s);
        }
    }
}

我使用的MilliTimer课程:

public class MilliTimer {
    private long startTime = 0L;

    private MilliTimer(long startTime){
        this.startTime = startTime;
    }

    public static MilliTimer start(){
        return new MilliTimer(System.currentTimeMillis());
    }

    public long end() throws IllegalArgumentException {
        return System.currentTimeMillis() - startTime;
    }
}

答案 2 :(得分:0)

Arrays.asList() method................: 22 ms
Arrays.stream() method................: 26 ms
Stream.of() method....................: 26 ms
Arrays.asList() (premade array) method: 8 ms
Arrays.stream() (premade array) method: 30 ms
Stream.of() (premade array) method....: 17 ms

当您将doSomething更改为实际上不执行任何操作时,如下所示:

public static void doSomething(String s){
}

然后你测量这些操作的实际速度而不是操作String = String + String;这就是doSomething正在做的事情,当然它的速度始终如一。但是,实际速度并不相同,而带有预制阵列的asList要快得多。

其他人已经注意到这里的真实结果,你应该注意流,因为它通常比普通的旧java(非lambda)方法慢4倍。