Arrays.asList vs. Arrays.stream to use forEach()

匿名 (未验证) 提交于 2019-12-03 02:30:02

问题:

If you have an Array and you want to use the Java8 forEach() method, which approach is better or more efficient:

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

or

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

Is the difference significant or are there any better solutions to solve this?

回答1:

Neither. If you already had an array,

String[] array; 

I would use:

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

because you leave the conversion of the array to a stream to the JDK - let it be responsible for efficiency etc.

But, since you don't have an array, I would use Stream.of()'s varargs to create a stream of the values:

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

Which again lets the JDK take the responsibility of efficiently streaming the values as it sees fit.



回答2:

It seems to make almost absolutely no difference. I created a test class for this. Over the course of five runs, my output was this:

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 

From the output, It looks like the Stream.of() method is very marginally (but consistently) the most efficent, and

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

is very readable code. Stream.of has the advantage in that it doesn't have to convert the array into a list, or create an array and then create a stream, but can create a stream directly from the elements. What was mildly surprising to me, was that because of the way I did my tests, it was faster to instantiate a new array stream each time with Stream.of() than it was to pass in a pre-made array, probably because "capturing" lambdas - those that reference an external variable - are a little less efficient.

Here's the code for my test class:

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);         }     } } 

And the MilliTimer class I used:

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;     } } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!