串/并行Stream流
package com.zenqgifeng.practicedemo.jdk8newproperties;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
/**
* @author zengqifeng
* @version 1.0
* @date 2020/1/3 9:57
* 基于collect方法
* 聚合计算 maxBy,minBy,avg..,sum..
* 分组 group
* 多级分组
* 分区 满足条件的分去true区,不满足条件的分去false区
* 连接 连接符,前缀,后缀
* 串行stream流和并行stream流
* 默认创建的就是串行stream流
* 并行stream流的两种创建方式
* 1、集合.parale...stream
* 2.Stream.parale....
* 串行stream和并行stream的效率对比
* 并行stream流可能出现线程安全问题体
* 线程安全问题解决办法
* 1、sync代码块包裹
* 2、Vector线程安全类集合
* 3、Collections.sync(Collection 推荐
* 4、toArray/collect(Colectors.toList)方法返回操作就是线程安全的
*/
public class Demo05 {
private static Long times = 500000000L;
private Long start;
private Long end;
private long sum;
@Before
public void init() {
sum = 0L;
start = System.currentTimeMillis();
}
@After
public void fianl() {
end = System.currentTimeMillis();
System.out.println("消耗时间:" + (end - start) + "毫秒");
}
/**
* 聚合计算
*/
@Test
public void test1() {
Stream<Student> stream = Stream.of(
new Student("张三", 20),
new Student("李四", 23),
new Student("王五", 18),
new Student("赵六", 26)
);
//求最大值
/*Optional<Student> max = stream.collect(Collectors.maxBy((s1, s2) -> s1.getAge() - s2.getAge()));
System.out.println("max:" + max);*/
//求最小值
/*Optional<Student> min = stream.collect(Collectors.minBy((s1, s2) -> s1.getAge() - s2.getAge()));
System.out.println("min:" + min);*/
//求和
/*Integer sum = stream.collect(Collectors.summingInt(Student::getAge));
System.out.println("sum:" + sum);*/
//求平均值
/*Double avg = stream.collect(Collectors.averagingInt(Student::getAge));
System.out.println("avg:" + avg);*/
//计数
Long count = stream.collect(Collectors.counting());
System.out.println("count:" + count);
}
/**
* 分组
*/
@Test
public void test2() {
Stream<Student> stream = Stream.of(
new Student("张三", 20, 89),
new Student("李四", 23, 90),
new Student("王五", 20 ,50),
new Student("赵六", 23, 56)
);
//根据年龄分组 返回的是啥就根据啥分组
/*Map<Integer, List<Student>> map = stream.collect(Collectors.groupingBy(Student::getAge));
map.forEach((k, y) -> {
System.out.println(k + "::" + y);
});*/
//超过60分为及格组
Map<String, List<Student>> map1 = stream.collect(Collectors.groupingBy((s) -> {
if (s.getScore() > 60) {
return "及格";
} else {
return "不及格";
}
}));
map1.forEach((x, y) -> {
System.out.println(x + "::" + y);
});
}
/**
* 多级分组
* 先根据年龄分组,再根据score分组
*/
@Test
public void test3() {
Stream<Student> stream = Stream.of(
new Student("张三", 20, 89),
new Student("李四", 23, 90),
new Student("王五", 20 ,50),
new Student("赵六", 23, 56)
);
Map<Integer, Map<String, List<Student>>> map = stream.collect(Collectors.groupingBy(Student::getAge, Collectors.groupingBy(s -> {
if (s.getScore() > 60) {
return "及格";
} else {
return "不及格";
}
})));
map.forEach((k1, v1) -> {
System.out.println(k1);
v1.forEach((k2, v2) -> {
System.out.println("\t" + k2 + "::" + v2);
});
});
}
/**
* 分区 true false
*/
@Test
public void test4() {
Stream<Student> stream = Stream.of(
new Student("张三", 20, 89),
new Student("李四", 23, 90),
new Student("王五", 20, 50),
new Student("赵六", 23, 56)
);
Map<Boolean, List<Student>> map = stream.collect(Collectors.partitioningBy(s -> {
if (s.getScore() > 60) {
return true;
} else {
return false;
}
}));
map.forEach((k, v) -> {
System.out.println(k + "::" + v);
});
}
/**
* join 连接
*/
@Test
public void test5() {
Stream<Student> stream = Stream.of(
new Student("张三", 20, 89),
new Student("李四", 23, 90),
new Student("王五", 20, 50),
new Student("赵六", 23, 56));
/*String names = stream.map(Student::getName).collect(Collectors.joining("-"));
System.out.println(names);*/
String names1 = stream.map(Student::getName).collect(Collectors.joining("-", "^_^", "V_V"));
System.out.println(names1);
}
/**
* 串行流和并行流
* 默认获取的就是串行流
*
* 并行流的获取方式
* list.parallel()
* Stream.parallel
*/
@Test
public void test6() {
Stream<Student> stream = Stream.of(
new Student("张三", 20, 89),
new Student("李四", 23, 90),
new Student("王五", 20, 50),
new Student("赵六", 23, 56));
/*long count = stream.filter(s -> {
System.out.println(Thread.currentThread().getId() + ":" + s.getAge());
return s.getScore() > 60;
}).count();*/
/*Stream<Student> parallel = stream.parallel();
long count = stream.filter(s -> {
System.out.println(Thread.currentThread().getId() + ":" + s.getAge());
return s.getScore() > 60;
}).count();*/
List<Student> list = new ArrayList<>();
Collections.addAll(list,new Student("张三", 20, 89),
new Student("李四", 23, 90),
new Student("王五", 20, 50),
new Student("赵六", 23, 56));
Stream<Student> studentStream = list.parallelStream();
long count = studentStream.filter(s -> {
System.out.println(Thread.currentThread().getId() + ":" + s.getAge());
return s.getScore() > 60;
}).count();
System.out.println(count);
}
/**
* 测试串行并行stream 普通之间的效率
* 当操作的数据量较大时使用并行stream效率明显高些
*/
@Test
public void testParallel() {
//消耗时间:1784毫秒
/*for (Long i = 0L; i < times; i++) {
sum += i;
}*/
//消耗时间:247毫秒
/*LongStream.rangeClosed(0, times).reduce(0, Long::sum);*/
//消耗时间:127毫秒
/*LongStream.rangeClosed(0, times).parallel().reduce(0, Long::sum);*/
LongStream.rangeClosed(0, times).parallel().reduce(0L, Long::sum);
}
/**
* 并行stream,线程安全问题
*/
@Test
public void testParallelSaveQuestion() {
//并行stream 可能出现线程安全问题
/*List<Integer> list = new ArrayList<>();
IntStream.rangeClosed(1, 1000).parallel().forEach(n -> {
list.add(n);
});*/
/*System.out.println(list.size());*/
//线程安全问题解决办法
//1、sync 同步代码块
/*List<Integer> newList = new ArrayList<>();
IntStream.rangeClosed(1, 1000).parallel().forEach(n -> {
//注意包裹范围,包裹可能出现线程安全的语句,范围不能大
synchronized (newList) {
newList.add(n);
}
});*/
//2、使用Vector
//3、使用Collections.sync....
/*List<Integer> list = new ArrayList<>();
//底层使用的是 CPU的 CAS指令 意思是比较再交换 效率高还好用 推荐
List<Integer> newList = Collections.synchronizedList(list);
IntStream.rangeClosed(1, 1000).parallel().forEach(n -> {
newList.add(n);
});*/
//4、调用stream流的toArray、collect方法就变成线程安全了
//IntStream LongStream等对应基本数据类型的流 消耗内存小且节省装箱拆箱时间
//自然这种流对应的功能也少些,比如它的collect方法就只有一种,需要装箱才能调用多种collect方法
List<Integer> newList = new ArrayList<>();
IntStream.rangeClosed(1, 1000).parallel().boxed().collect(Collectors.toCollection(ArrayList::new)).forEach(n -> {
newList.add(n);
});
System.out.println(newList.size());
}
}
class Student{
private String name;
private Integer age;
private Integer score;
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getScore() {
return score;
}
public void setScore(Integer score) {
this.score = score;
}
public Student(String name, Integer age, Integer score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
}