package stream;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class steamMain {
public static void main(String[] args) {
/**
* map函数
* 将流中的每⼀个元素 T 映射为 R(类似类型转换)
* 上堂课的例⼦就是,类似遍历集合,对集合的每个对象做处理
* 场景:转换对象,如javaweb开发中集合⾥⾯的DO对象转换为DTO对象
*/
List<String> list = Arrays.asList("springboot教程", "微服务教程", "并发编程", "压⼒测试", "架构课程");
List<String> li = Arrays.asList("asdad", "dfsfs", "erdsd", "zxcsdad", "weqqweqsd");
List<String> resultlist = list.stream().map(obj -> "我想学习" + obj).collect(Collectors.toList());
System.out.println(resultlist);
List<user> list1 = Arrays.asList(new user(12, "123"), new user(23, "234"), new user(24, "345"));
List<userDTO> resLIst = list1.stream().map(obj -> {
userDTO user = new userDTO();
user.setName(obj.getName());
return user;
}).collect(Collectors.toList());
System.out.println(resLIst);
/**
* filter 函数
* ⽤于通过设置的条件过滤出元素
* 需求:过滤出字符串⻓度⼤于5的字符串
*/
List<String> list2 = list.stream().filter(obj -> obj.length() > 4).collect(Collectors.toList());
System.out.println(list2);
/**
* sorted 函数
* sorted() 对流进⾏⾃然排序, 其中的元素必须实现Comparable 接⼝
*/
//默认升序
//List<String> list4 = li.stream().sorted(Comparator.comparing(String::length)).collect(Collectors.toList());
//反转 降序
//List<String> list4 = li.stream().sorted(Comparator.comparing(String::length).reversed()).collect(Collectors.toList());
List<String> list4 = li.stream().sorted(Comparator.comparing(String::length, Comparator.reverseOrder())).collect(Collectors.toList());
System.out.println(list4);
/**
* limit函数
* 截断流使其最多只包含指定数量的元素
*/
List<String> list5 = li.stream().limit(3).collect(Collectors.toList());
System.out.println(list5);
/**
* allMatch函数
* 检查是否匹配所有元素,只有全部符合才返回true
*/
boolean status = li.stream().allMatch(obj -> obj.length() > 4);
System.out.println(status);
/**
* anyMatch函数
* 检查是否⾄少匹配⼀个元素 只要又一个符合要求,返回true
*/
boolean status1 = li.stream().anyMatch(obj -> obj.length() > 10);
System.out.println(status1);
/**
* max函数
*/
// Optional<user> list7 = list1.stream().max(Comparator.comparingInt(user::getAge));
Optional<user> list7 = list1.stream().max((s1, s2) -> Integer.compare(s1.getAge(), s2.getAge()));
System.out.println(list7.get().getAge());
/**
* min函数
*/
//Optional<user> list8 =list1.stream().min(Comparator.comparingInt(user::getAge));
Optional<user> list8 = list1.stream().min((s1, s2) -> Integer.compare(s1.getAge(), s2.getAge()));
System.out.println(list8.get().getAge());
/**
* 并行流 parallelStream
* 为什么会有这个并⾏流
* 集合做重复的操作,如果使⽤串⾏执⾏会相当耗时,因此⼀般会采⽤多线程来加快, Java8的
* paralleStream⽤fork/join框架提供了并发执⾏能⼒
* 底层原理
* 线程池(ForkJoinPool)维护⼀个线程队列
* 可以分割任务,将⽗任务拆分成⼦任务,完全贴合分治思想
*
* paralleStream并⾏是否⼀定⽐Stream串⾏快?
* 错误,数据量少的情况,可能串⾏更快,ForkJoin会耗性能
* 多数情况下并⾏⽐串⾏快,是否可以都⽤并⾏
* 不⾏,部分情况会有线程安全问题,parallelStream⾥⾯使⽤的外部变量,⽐如集合⼀
* 定要使⽤线程安全集合,不然就会引发多线程安全问题
*/
//两种区别
System.out.println("Stream输出集合");
li.stream().forEach(System.out::println);
System.out.println("parallelStream");
li.parallelStream().forEach(System.out::println);
//使用parallelStream有线程安全问题,所以集合对象需要集合安全的对象
//循环10次
for (int i = 0; i < 10; i++) {
//arrayList的添加方法没有加锁,线程不安全
//List paralleList = new ArrayList();
List paralleList = new CopyOnWriteArrayList();
//生成0到100的数,并行的加入到数组
IntStream.range(0, 100).parallel().forEach(paralleList::add);
//如果是用的是ArrayList 这里会报数组下标越界异常,原因ArrayLits的add方法没有加锁,循环到了第9次时,因为是多线程,查看size的时候,都同时加1了,导致下标越界。
//换成CopyOnWriteArrayList集合则不会,因为CopyOnWriteArrayList集合的add方法有加锁
System.out.println(paralleList.size());
}
/**
* reduce操作
* 什么是reduce操作
* 聚合操作,中⽂意思是 “减少”
* 根据⼀定的规则将Stream中的元素进⾏计算后返回⼀个唯⼀的值
* 常⽤⽅法⼀
Optional<T> reduce(BinaryOperator<T> accumulator);
*/
//累加器
int value = Stream.of(1, 2, 3, 4, 5, 6).reduce((item1, item2) -> item1 + item2).get();
System.out.println(value);
//带起始值的累加器
int value1 = Stream.of(1, 2, 3, 4, 5, 6).reduce(100, (item1, item2) -> item1 + item2);
System.out.println(value1);
//使用reduce求出最大值
int value2 = Stream.of(213, 2312, 12, 454).reduce((item1, item2) -> item1 > item2 ? item1 : item2).get();
System.out.println(value2);
/**
* foreach操作
* 集合遍历的⽅式
* for循环
* 迭代器 Iterator
*
* Jdk8⾥⾯的新增接⼝
* default void forEach(Consumer<? super T> action) {
* Objects.requireNonNull(action);
* for (T t : this) {
* action.accept(t);
* }
* }
*
* 注意点
* 不能修改包含外部的变量的值
* 不能⽤break或者return或者continue等关键词结束或者跳过循环
*/
list1.stream().forEach(obj -> System.out.println(obj));
int totalAge = 0;
//测试修改包含外部的变量的值
// list1.stream().forEach(obj ->{
// System.out.println(obj);
// totalAge += obj.getAge();
// });
//测试⽤break或者return或者continue等关键词结束或者跳过循环
// li.stream().forEach(obj ->{
// System.out.println(obj);
// return;
// });
/**
* collector 收集器
* ⼀个终端操作, ⽤于对流中的数据进⾏归集操作,collect⽅法接受的参数是⼀个Collector
* 有两个重载⽅法,在Stream接⼝⾥⾯
* default void forEach(Consumer<? super T> action) {
* Objects.requireNonNull(action);
* for (T t : this) {
* action.accept(t);
* }
* }
* List<Student> results = Arrays.asList(new Student(32),new
* Student(33),new Student(21),new Student(29),new Student(18));
* results.forEach(obj->{
* System.out.println(obj.toString());
* });
* Collector的作⽤
* 就是收集器,也是⼀个接⼝, 它的⼯具类Collectors提供了很多⼯⼚⽅法
* Collectors 的作⽤
* ⼯具类,提供了很多常⻅的收集器实现
* Collectors.toList()
* ArrayList::new,创建⼀个ArrayList作为累加器
* List::add,对流中元素的操作就是直接添加到累加器中
* reduce操作, 对⼦任务归集结果addAll,后⼀个⼦任务的结果直接全部添加到
* 前⼀个⼦任务结果中
* CH_ID 是⼀个unmodifiableSet集合
* Collectors.toMap()
* Collectors.toSet()
* Collectors.toCollection() :⽤⾃定义的实现Collection的数据结构收集
* Collectors.toCollection(LinkedList::new)
* Collectors.toCollection(CopyOnWriteArrayList::new)
* Collectors.toCollection(TreeSet::new)
*/
List<String> listStr = Stream.of("dsad", "dasdsa", "123dsa").collect(Collectors.toList());
System.out.println(listStr);
//set集合
Set<String> setStr = Stream.of("dsad", "dasdsa", "123dsa", "123dsa").collect(Collectors.toSet());
System.out.println(setStr);
Set<String> setStr1 = Stream.of("dsad", "dasdsa", "123dsa", "123dsa").collect(Collectors.toCollection(TreeSet::new));
System.out.println(setStr1);
List<String> listStr1 = Stream.of("dsad", "dasdsa", "123dsa", "123dsa").collect(Collectors.toCollection(ArrayList::new));
System.out.println(listStr1);
/**
* join函数
* 拼接函数 Collectors.joining
* //重载⽅法⼀
* <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T>
* accumulator, BiConsumer<R, R>combiner);
* //重载⽅法⼆
* <R, A> R collect(Collector<? super T, A, R> collector);
* public static <T> Collector<T, ?, List<T>> toList() {
* return new CollectorImpl<>((Supplier<List<T>>)
* ArrayList::new, List::add,(left, right) -> {
* left.addAll(right); return left; }, CH_ID);
* }
* 其中⼀个的实现
* 说明:
* 该⽅法可以将Stream得到⼀个字符串, joining函数接受三个参数,分别表示 元素之间的连
* 接符、前缀和后缀。
*/
//将数组集合"||"拼接在一起
String value3 = list.stream().collect(Collectors.joining("||"));
System.out.println(value3);
//还可以使用join函数,指定前缀和后缀
String value4 = list.stream().collect(Collectors.joining("||", "{", "}"));
System.out.println(value4);
/**
* partitioningBy分组
* Collectors.partitioningBy 分组,key是boolean类型
* public static <T>
* Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super
* T> predicate) {
* return partitioningBy(predicate, toList());
* }
*/
//将数组长度大于5的字符串分出来
Map<Boolean,List<String>> boMap = li.stream().collect(Collectors.partitioningBy(obj -> obj.length() > 5));
boMap.forEach((k,v) ->{
System.out.println(k+"->"+v);
});
/**
* groupby 分组
* 分组 Collectors.groupingBy()
* public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(Function<?
* super T, ? extends K> classifier) { return groupingBy(classifier, toList());
* }
*/
//练习:根据学⽣所在的省份,进⾏分组
List<Student> studentList = Arrays.asList(new Student("⼴东", 23), new
Student("⼴东", 24), new Student("⼴东", 23),new Student("北京", 22), new
Student("北京", 20), new Student("北京", 20),new Student("海南", 25));
Map<String,List<Student>> stuMap = studentList.stream().collect(Collectors.groupingBy(obj -> obj.getProvince()));
stuMap.forEach((k,v)->{
System.out.println(k+"有"+v);
});
//算出每个地区有多少人
/**
* 分组统计,groupby分组进阶
* 分组后进行统计Collectors.counting() 统计元素个数
*/
Map<String,Long> longMap = studentList.stream().collect(Collectors.groupingBy(obj -> obj.getProvince(),Collectors.counting()));
longMap.forEach((k,v)->{
System.out.println(k+"有"+v+"人");
});
/**
* groupby分组进阶
* summarizing集合统计
* 作⽤:可以⼀个⽅法把统计相关的基本上都完成
* 分类
* summarizingInt
* summarizingLong
* summarizingDouble
*/
IntSummaryStatistics summaryStatistics = studentList.stream().collect(Collectors.summarizingInt(obj -> obj.getAge()));
System.out.println("平均年龄"+summaryStatistics.getAverage());
System.out.println("总人数"+summaryStatistics.getCount());
System.out.println("最大年龄"+summaryStatistics.getMax());
System.out.println("最小年龄"+summaryStatistics.getMin());
}
}
package stream;
public class Student {
private String province;
private int age;
public Student() {
}
public Student(String province, int age) {
this.province = province;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"province='" + province + '\'' +
", age=" + age +
'}';
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package stream;
public class user {
private int age;
private String name;
public user(int age, String name) {
this.age = age;
this.name = name;
}
public user() {
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "user{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
package stream;
public class userDTO {
private String name;
public userDTO(String name) {
this.name = name;
}
public userDTO() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}