Stream流简介
Stream的操作步骤
1、创建Stream流
2、中间流水线操作
3、终止操作,产生需要的结果源数据
注意:Stream流和最终产生的结果不影响
创建Stream的代码示例
List<String> list = Arrays.asList("Sarah", "Terry", "Selina", "Tom");
// 创建Stream
@Test
public void test01(){
// 1、通过Collection提供的stream()或者 paralleStream()
Stream<String> stream01 = list.stream();
// 2、通过Stream类的静态方法of()
Stream<String> stream02 = Stream.of("aa", "bb", "cc");
// 3、通过Arrays的静态方法 stream() 获取数组流
Stream<Integer> stream03 = Arrays.stream(new Integer[]{1,1,1});
// 4、创建无限流
Stream<Integer> stream04 = Stream.iterate(0,(x) -> x+2);
stream04.limit(10).forEach(System.out::println);
}
Stream的中间操作:筛选与切片
代码示例:
List<String> strList = Arrays.asList("Sarah", "Terry", "Selina", "Tom", "Selina", "Terry");
List<Employee> employeeList = Arrays.asList(
new Employee("张三",18,2000),
new Employee("李四",58,3000),
new Employee("王五",48,7000),
new Employee("陈六",38,9000),
new Employee("田七",18,9000),
new Employee("田七",18,9000),
new Employee("田七",18,9000)
);
//中间操作
/**
* 筛选与切片
* filter:从流中排除某些元素
* limit(n):从流中取不超过给n的元素
* skip(n):返回一个去掉前n个元素的流,若流中元素不超过n,返回一个空流,与limit互补
* distinct:根据hashCode()和equals()对元素去重
*/
// filter
@Test
public void test01(){
// 中间操作
Stream<String> stream = strList.stream().filter((x) -> x.length() > 3);
// 终止操作
stream.forEach(System.out::println);
}
// limit
@Test
public void test02(){
employeeList.stream().limit(2).forEach(System.out::println);
}
// skip
@Test
public void test03(){
employeeList.stream().skip(2).forEach(System.out::println);
}
// distinct
@Test
public void test04(){
strList.stream().distinct().forEach(System.out::println);
}
// 惰性求值
@Test
public void test05(){
employeeList.stream()
.filter((x) -> {
System.out.println("短路");
return x.getAge() >50;
})
.limit(2)
.forEach(System.out::println);
}
惰性求值
Stream的中间操作:映射
代码示例
List<String> strList = Arrays.asList("aa", "bb", "cc");
List<Employee> employeeList = Arrays.asList(
new Employee("张三",18,2000),
new Employee("李四",58,3000),
new Employee("王五",48,7000),
new Employee("陈六",38,9000),
new Employee("田七",18,9000),
new Employee("田七",18,9000),
new Employee("田七",18,9000)
);
//中间操作
/**
* 映射
* map:接受Lamda,将元素转换成其他形式或提取信息。接受一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素
* flatMap:接收一个函数作为参数,将流中的每个值转换成另一个流,然后把所有的流连接成一个流
* skip(n):
* distinct:
*/
// map
@Test
public void test01(){
employeeList.stream().map(e -> e.getName()).forEach(System.out::println);
}
// flatMap
@Test
public void test02(){
strList.stream().map(s -> s.toUpperCase()).forEach(System.out::println);// {AA, BB, CC}
strList.stream().flatMap(s -> filterCharacter(s)).forEach(System.out::println);// {a, a, b, b, c, c}
}
private Stream<Character> filterCharacter(String str){
List<Character> list = new ArrayList<>();
for (char c : str.toCharArray()) {
list.add(c);
}
return list.stream();
}
Stream的中间操作:排序
代码示例
List<Employee> employeeList = Arrays.asList(
new Employee("张三",18,2000),
new Employee("李四",58,3000),
new Employee("王五",48,7000),
new Employee("陈六",38,9000),
new Employee("田七",18,9000),
new Employee("田七",18,9000),
new Employee("田七",18,9000)
);
//中间操作
/**
* 排序
* sorted():自然排序
* sorted(Comparactor com):定制排序
*/
// sorted()
@Test
public void test01(){
employeeList.stream().map(e -> e.getAge()).sorted().forEach(System.out::println);
}
// sorted(Comparactor com)
@Test
public void test02(){
employeeList.stream().sorted((e1, e2) -> {
if(e1.getAge() == e2.getAge()){
return e1.getName().compareTo(e2.getName());
}else {
return -Integer.compare(e1.getAge(), e2.getAge());
}
}).forEach(System.out::println);
}
Stream的终止操作:查找与匹配
代码示例:
List<Employee> employeeList = Arrays.asList(
new Employee("张三",18,2000, Employee.Status.BUSY),
new Employee("李四",58,3000, Employee.Status.FREE),
new Employee("王五",48,7000, Employee.Status.VOCATION),
new Employee("陈六",38,9000, Employee.Status.BUSY),
new Employee("田七",18,9000, Employee.Status.BUSY),
new Employee("王二",18,9000, Employee.Status.BUSY),
new Employee("田七",18,9000, Employee.Status.VOCATION)
);
//终止操作
/**
* 查找与匹配
* allMatch():检查是否匹配所有元素
* anyMatch():检查是否至少匹配一个元素
* noneMatch():检查是否一个元素都没有匹配到
* findFirst():返回第一个元素
* findAny():返回任意一个元素
* count():统计元素的总个数
* max():返回流中的最大值
* min():返回流中的最小值
*/
// allMatch()
@Test
public void test01(){
boolean b = employeeList.stream().allMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
System.out.println(b);
}
// anyMatch()
@Test
public void test02(){
boolean b = employeeList.stream().anyMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
System.out.println(b);
}
// noneMatch()
@Test
public void test03(){
boolean b = employeeList.stream().noneMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
System.out.println(b);
}
// findFirst()
@Test
public void test04(){
Optional<Employee> e = employeeList.stream().findFirst();
System.out.println(e.get());
}
// findAny()
@Test
public void test05(){
// parallelStream为并行流
Optional<Employee> employee = employeeList.parallelStream().filter((e) -> e.getStatus().equals(Employee.Status.BUSY)).findAny();
System.out.println(employee.get());
}
// count()
@Test
public void test06(){
long count = employeeList.stream().count();
System.out.println(count);
}
// max(Comparator com)
@Test
public void test07(){
Optional<Employee> e = employeeList.stream().max((e1, e2) -> {
if(e1.getAge() == e2.getAge()){
return e1.getName().compareTo(e2.getName());
}else {
return Integer.compare(e1.getAge(), e2.getAge());
}
});
System.out.println(e.get());
}
// min(Comparator com)
@Test
public void test08(){
Optional<Employee> e = employeeList.stream().min((e1, e2) -> {
if(e1.getAge() == e2.getAge()){
return e1.getName().compareTo(e2.getName());
}else {
return Integer.compare(e1.getAge(), e2.getAge());
}
});
System.out.println(e.get());
}
// 串行流与并行流
/**
* 串行流:适合存在线程安全问题、阻塞任务、重量级任务,以及需要使用同一事务的逻辑。
* 并行流:适合没有线程安全问题、较单纯的数据处理任务。
*/
@Test
public void test09(){
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
numbers.stream().forEach(System.out::print);
// 输出结果是固定的
// 123456789
numbers.parallelStream().forEach(System.out::print);
// 输出结果是不固定的
// 652879314
//打印并查看线程信息
numbers.parallelStream().forEach((num) -> System.out.println(Thread.currentThread().getName()+">>"+num));
// ForkJoinPool.commonPool-worker-7>>3
// ForkJoinPool.commonPool-worker-2>>4
// ForkJoinPool.commonPool-worker-3>>9
// ForkJoinPool.commonPool-worker-5>>2
// ForkJoinPool.commonPool-worker-1>>7
// ForkJoinPool.commonPool-worker-4>>5
// ForkJoinPool.commonPool-worker-6>>8
// main>>6
// ForkJoinPool.commonPool-worker-7>>1
}
Stream的终止操作:归约
代码示例:
List<Employee> employeeList = Arrays.asList(
new Employee("张三",18,2000, Employee.Status.BUSY),
new Employee("李四",58,3000, Employee.Status.FREE),
new Employee("王五",48,7000, Employee.Status.VOCATION),
new Employee("陈六",38,9000, Employee.Status.BUSY),
new Employee("田七",18,9000, Employee.Status.BUSY),
new Employee("王二",18,9000, Employee.Status.BUSY),
new Employee("田七",18,9000, Employee.Status.VOCATION)
);
//终止操作
/**
* 归约
* reduce(T identity, BinaryOpertor) / reduce(BinaryOpertor) --可以将流中的元素反复结合起来,得到一个值
*
* map和reduce的连接通常被成为map-reduce模式,因Google用其来做网络搜索而出名
*/
// reduce()
@Test
public void test01(){
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9);
Integer sum = list.stream().reduce(0, (x, y) -> x+y);
System.out.println(sum);
// reduce中的 x+y 的执行过程
// 0+1=1
// 1+2=3
// 3+3=6
// ...
// 36+9=45
}
@Test
public void test02(){
Optional<Integer> sum = employeeList.stream().map(e -> e.getAge()).reduce((x, y) -> x+y);
System.out.println(sum.get());
}
Stream的终止操作:内部迭代
Stream的终止操作:收集
Collector中的方法实现了对流的收集操作(如收集到List、Set、Map)。
Collectors实用类提供了很多静态方法,可以方便地创建收集器实例。
代码示例:
List<Employee> employeeList = Arrays.asList(
new Employee("张三",18,2000, Employee.Status.BUSY),
new Employee("李四",58,3000, Employee.Status.FREE),
new Employee("王五",48,7000, Employee.Status.VOCATION),
new Employee("陈六",38,9000, Employee.Status.BUSY),
new Employee("田七",18,9000, Employee.Status.BUSY),
new Employee("王二",18,9000, Employee.Status.BUSY),
new Employee("田七",18,9000, Employee.Status.VOCATION)
);
//终止操作
/**
* 收集
* collector -- 将流转换为其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
*/
// reduce()
@Test
public void test01(){
List<String > list = employeeList.stream().map(Employee::getName).collect(Collectors.toList());
list.forEach(System.out::println);
System.out.println("-----------------------");
Set<String> set = employeeList.stream().map(Employee::getName).collect(Collectors.toSet());
set.forEach(System.out::println);
System.out.println("-----------------------");
HashSet<String> hs = employeeList.stream().map(Employee::getName).collect(Collectors.toCollection(HashSet::new));
hs.forEach(System.out::println);
//等同于以下的写法
HashSet<String> hashSet = employeeList.stream().map(Employee::getName).collect(Collectors.toCollection(new Supplier<HashSet<String>>() {
@Override
public HashSet<String> get() {
return new HashSet<>();
}
}));
hashSet.forEach(System.out::println);
}
// 求和、求平均值、求最大值、求最小值
@Test
public void test02(){
// 求所有age的平均值
Double ave = employeeList.stream().collect(Collectors.averagingInt(Employee::getAge));
// 求所有age的总和
Integer sum = employeeList.stream().collect(Collectors.summingInt(Employee::getAge));
// 求age最大的Employee
Optional<Employee> max = employeeList.stream()
.collect(Collectors.maxBy((o1, o2) -> Integer.compare(o1.getAge(), o2.getAge())));
// 求age最小的Employee
Optional<Employee> min = employeeList.stream().collect(Collectors.minBy((o1, o2) -> Integer.compare(o1.getAge(), o2.getAge())));
}
// 分组
@Test
public void test03(){
Map<Employee.Status, List<Employee>> map = employeeList.stream().collect(Collectors.groupingBy(Employee::getStatus));
}
// 多级分组
@Test
public void test04(){
Map<Employee.Status, Map<String, List<Employee>>> map = employeeList.stream().collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {
if(e.getAge() <= 35){
return "青年";
}else if((e.getAge() >= 35) && (e.getAge()<= 50)){
return "中年";
}else {
return "老年";
}
})));
System.out.println(map);
}
// 分区
@Test
public void test05(){
Map<Boolean, List<Employee>> map = employeeList.stream().collect(Collectors.partitioningBy(e -> e.getSalary() > 8000));
System.out.println(map);
}
@Test
public void test06(){
DoubleSummaryStatistics dss = employeeList.stream().collect(Collectors.summarizingDouble(Employee::getSalary));
System.out.println(dss.getMax());
System.out.println(dss.getAverage());
System.out.println(dss.getMin());
System.out.println(dss.getSum());
}
@Test
public void test07(){
String str = employeeList.stream().map(Employee::getName).collect(Collectors.joining(",", "--", "++"));
System.out.println(str);
}