1.Stream并行流的使用方式
1. stream().parallel()
先将集合Collection转换成Stream流的形式,再将流转换为并行流
2. parallelStream()
直接将Colletion集合转换为并行流
stream().parallel() 和 parallelStream()两种获取并行流 并且执行任务的时间消耗相差无几 可以忽略不计
2.并行流使用注意!!
- 并行流的操作大多用来处理一些cpu密集型任务,也就是说多数用来处理计算任务,而不是io任务,io任务一半交由线程层池来完成,因为线程池在执行任务时,并不会阻塞当前调用线程,而并行流却是在调用线程中执行的,在并行流中执行io操作会导致调用线程被阻塞,知道io任务结束
- 并行流一般用于执行计算任务,如果涉及到需要使用共享可变的参数,还需要考虑线程安全的问题
3.使用Stream和for循环的区别
我们在需要对某一列表进行遍历时大多有两种方式,一种是for循环,另外一种就是stream,但是在使用他们时,有什么区别呢
@Test
public void parallelStreamTest() {
List<String> lessStringList = generateRandomString(10000);
List<String> moreStringList = generateRandomString(40000);
long forStart = System.currentTimeMillis();
List<String> strings = forMethod(moreStringList, lessStringList);
long forEnd = System.currentTimeMillis();
System.out.println("for 循环耗时:" + (forEnd - forStart) + " ms");
long streamStart = System.currentTimeMillis();
List<String> streamStrList= streamMethod(moreStringList, lessStringList);
long streamEnd = System.currentTimeMillis();
System.out.println("stream 循环耗时:" + (streamEnd - streamStart) + " ms");
long parallelStreamStart = System.currentTimeMillis();
List<String> parallelStreamStrList= parallelStreamMethod(moreStringList, lessStringList);
long parallelStreamEnd = System.currentTimeMillis();
System.out.println("parallelStream 循环耗时:" + (parallelStreamEnd - parallelStreamStart) + " ms");
long streamParallelStart = System.currentTimeMillis();
List<String> streamParallelStrList= streamParallelMethod(moreStringList, lessStringList);
long streamParallelEnd = System.currentTimeMillis();
System.out.println("streamParallel 循环耗时:" + (streamParallelEnd - streamParallelStart) + " ms");
}
private List<String> forMethod(List<String> moreStringList, List<String> lessStringList) {
List<String> addList = new ArrayList<>();
for (String productCode : moreStringList) {
boolean exist = false;
for (String str : lessStringList) {
if (productCode.equals(str)) {
exist = true;
break;
}
}
if (!exist) {
addList.add(productCode);
}
}
return addList;
}
/*
使用stream在处理这种简单循环时 可能比普通for循环花费的时间更多
,因为使用stream 会造成一些额外的流处理的开销
*/
private List<String> streamMethod(List<String> moreStringList, List<String> lessStringList) {
return moreStringList.stream().filter(more -> lessStringList.stream()
.noneMatch(less -> less.equals(more)))
.collect(Collectors.toList());
}
private List<String> parallelStreamMethod(List<String> moreStringList, List<String> lessStringList) {
return moreStringList.parallelStream().filter(more -> lessStringList.stream()
.noneMatch(less -> less.equals(more)))
.collect(Collectors.toList());
}
private List<String> streamParallelMethod(List<String> moreStringList, List<String> lessStringList) {
return moreStringList.stream().parallel().filter(more -> lessStringList.stream()
.noneMatch(less -> less.equals(more)))
.collect(Collectors.toList());
}
public static List<String> generateRandomString(int size) {
List<String> list = new ArrayList<>();
String CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
for (int j = 0; j < size; j++) {
Random random = new Random();
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < 10; i++) {
int randomIndex = random.nextInt(CHARACTERS.length());
char randomChar = CHARACTERS.charAt(randomIndex);
stringBuilder.append(randomChar);
}
list.add(stringBuilder.toString());
}
return list;
}
由上述代码自行测试可知,有时候stream这种看起来高大上的东西在进行一些简单的循环操作时,还不如for循环来的效率高,这是因为使用stream的方法前要先将我们的列表转换成流的形式,造成额外的开销
,因此建议,在进行一些简单操作时,推荐使用for循环来完成,有时使用stream并不会提升效率,相反还会降低效率,增加额外开销