packagestream;import java.util.*;importjava.util.concurrent.CopyOnWriteArrayList;importjava.util.stream.Collectors;importjava.util.stream.IntStream;importjava.util.stream.Stream;public classsteamMain {public static voidmain(String[] args) {/*** map函数
* 将流中的每⼀个元素 T 映射为 R(类似类型转换)
* 上堂课的例⼦就是,类似遍历集合,对集合的每个对象做处理
* 场景:转换对象,如javaweb开发中集合⾥⾯的DO对象转换为DTO对象*/List list = Arrays.asList("springboot教程", "微服务教程", "并发编程", "压⼒测试", "架构课程");
List li = Arrays.asList("asdad", "dfsfs", "erdsd", "zxcsdad", "weqqweqsd");
List resultlist = list.stream().map(obj -> "我想学习" +obj).collect(Collectors.toList());
System.out.println(resultlist);
List list1 = Arrays.asList(new user(12, "123"), new user(23, "234"), new user(24, "345"));
List resLIst = list1.stream().map(obj ->{
userDTO user= newuserDTO();
user.setName(obj.getName());returnuser;
}).collect(Collectors.toList());
System.out.println(resLIst);/*** filter 函数
* ⽤于通过设置的条件过滤出元素
* 需求:过滤出字符串⻓度⼤于5的字符串*/List list2 = list.stream().filter(obj -> obj.length() > 4).collect(Collectors.toList());
System.out.println(list2);/*** sorted 函数
* sorted() 对流进⾏⾃然排序, 其中的元素必须实现Comparable 接⼝*/
//默认升序//List list4 = li.stream().sorted(Comparator.comparing(String::length)).collect(Collectors.toList());//反转 降序//List list4 = li.stream().sorted(Comparator.comparing(String::length).reversed()).collect(Collectors.toList());
List list4 =li.stream().sorted(Comparator.comparing(String::length, Comparator.reverseOrder())).collect(Collectors.toList());
System.out.println(list4);/*** limit函数
* 截断流使其最多只包含指定数量的元素*/List 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 list7 = list1.stream().max(Comparator.comparingInt(user::getAge));
Optional list7 = list1.stream().max((s1, s2) ->Integer.compare(s1.getAge(), s2.getAge()));
System.out.println(list7.get().getAge());/*** min函数*/
//Optional list8 =list1.stream().min(Comparator.comparingInt(user::getAge));
Optional 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 = newCopyOnWriteArrayList();//生成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 reduce(BinaryOperator 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 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 listStr = Stream.of("dsad", "dasdsa", "123dsa").collect(Collectors.toList());
System.out.println(listStr);//set集合
Set setStr = Stream.of("dsad", "dasdsa", "123dsa", "123dsa").collect(Collectors.toSet());
System.out.println(setStr);
Set setStr1 = Stream.of("dsad", "dasdsa", "123dsa", "123dsa").collect(Collectors.toCollection(TreeSet::new));
System.out.println(setStr1);
List listStr1 = Stream.of("dsad", "dasdsa", "123dsa", "123dsa").collect(Collectors.toCollection(ArrayList::new));
System.out.println(listStr1);/*** join函数
* 拼接函数 Collectors.joining
* //重载⽅法⼀
* R collect(Supplier supplier, BiConsumer
* accumulator, BiConsumercombiner);
* //重载⽅法⼆
* R collect(Collector super T, A, R> collector);
* public static Collector> toList() {
* return new CollectorImpl<>((Supplier>)
* 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
* Collector>> partitioningBy(Predicate super
* T> predicate) {
* return partitioningBy(predicate, toList());
* }*/
//将数组长度大于5的字符串分出来
Map> boMap = li.stream().collect(Collectors.partitioningBy(obj -> obj.length() > 5));
boMap.forEach((k,v)->{
System.out.println(k+"->"+v);
});/*** groupby 分组
* 分组 Collectors.groupingBy()
* public static Collector>> groupingBy(Function
* super T, ? extends K> classifier) { return groupingBy(classifier, toList());
* }*/
//练习:根据学⽣所在的省份,进⾏分组
List studentList = Arrays.asList(new Student("⼴东", 23), newStudent("⼴东", 24), new Student("⼴东", 23),new Student("北京", 22), newStudent("北京", 20), new Student("北京", 20),new Student("海南", 25));
Map> stuMap = studentList.stream().collect(Collectors.groupingBy(obj ->obj.getProvince()));
stuMap.forEach((k,v)->{
System.out.println(k+"有"+v);
});//算出每个地区有多少人
/*** 分组统计,groupby分组进阶
* 分组后进行统计Collectors.counting() 统计元素个数*/Map 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());
}
}