WorkProj
内容管理
- Stream
- 中间操作 (流不会关闭)
- filter(x -> x boolean表达式) 筛选返回值为true的
- distinct() 去重
- limit(X) 返回前x个元素
- skip(x) 跳过流中元素
- map(x操作) 对每一个元素映射操作
- mapToInt() 将对象流转为数值流 Integer --> int
- flatMap(x操作) 将一个流中每一个值转为流 【针对对象为集合/array】合并集合
- sorted(Comparator.comparing(字段)) 将stream中元素排序
- 终端操作 (关闭流), 返回值
- allMatch(x -> x boolean表达式) 当stream中所有元素满足条件返回true
- anyMatch(x -> x boolean表达式) 当stream中一个元素满足就返回true
- noneMatch(x -> x boolean表达式) 全部不满足返回true
- count() 统计流中元素个数
- findFirst() 返回流中第一个元素
- findAny() 返回流中随机一个元素
- max/min () 返回流中的最大最小值
- sum() 求和
- foreach() 遍历
- reduce 将流中的元素组合 ⭐ 可替代max、min、sum等
- collect 返回集合 collect策略有很多 ---> ⭐ 可执行sum、average...等
- 类型归纳 --- 转为集合容器 toXXX
- joining 将元素用某规则连接起来
- collectingAndThen 先对结果进行归纳,之后再进行Function函数处理结果
- groupingBy 按照条件对结果分组
- counting 对收集的结果求和
- mapping(mapper, downSream) 在Collect中进行隐射
- maxBy(comparator)/minBy
- summingInt/Double/Long(元素 -- 可用Lambda)
- summarizingDouble/Int/Long⭐ 统计量: 包括总数 和 max/min 平均值
- reducing ⭐ (T, T) -> T 元素两两比较淘汰一个(一轮轮reduce)
本文introduce 对于Stream的使用
在关系型数据库中处理数据还是很easy的,使用group by , order by等关键字可以方便查出各种数据
但是很多场景下数据不是在数据库中处理, 而是直接拎到内存中处理, 这个时候Stream就可以发挥巨大作用【相较于传统的for遍历】
比如java的dynamicSqlBuilder, 动态SQL查询出动态数据库表中的数据【所有都是动态的】, 这里的返回值就是List<Map<String, Object>>
要对List<Map<String,Object>>进行处理, 通过Stream的方式就是最快的
流stream是支持数据处理操作的源生成的元素序列, 源可以是数组、文件、集合、函数; Stream不是集合,不是数据结构,主要目的就是计算
Stream
Stream创建方式一共有5种, 集合、数组、of值、文件、函数iterator无限流
- 最常见的就是通过集合Collection生成
Stream stream = distinctMap.values().stream
除此之外,也可以通过数组Arrays.sttream(数组)、 Stream.of(值1, 值2…)、Files.lines(文件)、 Stream.iterator(xxx)无限流 | Stream.generator(xxx)无限流
流Stream的操作分为两种:
- 中间操作: 一个流后面可以跟随0或者多个中间操作,
打开流做出某种程度的映射
, 操作是惰性化的,没有真正开始流的遍历, 常见的map、filter都是 - 终端操作: 一个流只能有一个终端操作,
进行流的遍历
,操作执行后,流就关闭了,不能再操作,因此一个流只能遍历一次,如collect、count
中间操作 (流不会关闭)
中间操作可以为 0 ~ 多个, 一定程度的映射和操作
比如List list = Arrays.asList(1,1,2,3,4,5,6);
filter(x -> x boolean表达式) 筛选返回值为true的
list.stream().filter(item -> item > 3)//这里的item代表的就是流中的每一个元素,可以使用Lambda表达式
//4,5,6
distinct() 去重
list.stream().distinct()//结果1,2,3,4,5,6
limit(X) 返回前x个元素
这个和数据库limit类似
list.stream().limit(3)//1,1,2
skip(x) 跳过流中元素
和limit相反,跳过前X个元素
list.stream().skip(3)//3,4,5,6
map(x操作) 对每一个元素映射操作
操作位置可以使用Lambda或者函数引用
list.stream().map(x -> x + 1)//2,2,3,4,5,6,7
mapToInt() 将对象流转为数值流 Integer --> int
flatMap(x操作) 将一个流中每一个值转为流 【针对对象为集合/array】合并集合
这个和Map的不同主要就是针对List<List<>>的情况, 一层流只能得到List, 要想直接得到最内层对象,就只能flatMap, 会将所有的List全转化为流
List<List《Stream>> strList = [[“java,python”], [“cfeng”,“cshen”]]
strList.stream().flatMap(item -> item.Stream())
sorted(Comparator.comparing(字段)) 将stream中元素排序
这个sorted中可以给出字段,就是按照默认的顺序排序,加上.reversed()
就可以倒序,当然也可以使用Lambda表达式进行定制的排序
list.stream.sorted(Comparator.comparing(Book:: getPublishTime).reversed())
终端操作 (关闭流), 返回值
终端操作只能一个, 会对流进行遍历(和requestBody一样,只能一次性)
allMatch(x -> x boolean表达式) 当stream中所有元素满足条件返回true
if(list.stream.allMatch(item -> item > 3))//这里false,因为1,1,2,3几个元素不满足
anyMatch(x -> x boolean表达式) 当stream中一个元素满足就返回true
if(list.stream.anyMatch(item -> item > 5))//true,因为6这个元素满足
noneMatch(x -> x boolean表达式) 全部不满足返回true
if(list.stream.noneMatch(item -> item > 5))//false,因为6这个元素满足
count() 统计流中元素个数
list.stream().count()
//个数7
findFirst() 返回流中第一个元素
list.stream().findFirst()
//1
findAny() 返回流中随机一个元素
list.stream().findAny()
//4 , 随机的
max/min () 返回流中的最大最小值
list.stream().min(Integer::CompareTo)list.stream().min()//1
sum() 求和
list.stream().sum() //可以用lambda统计元素, 比如str.length求和//1 + 1 + 2 + 3 + 4 + 5 + 6
foreach() 遍历
list.stream().foreach(System::println);
//1 /n 1 .....
reduce 将流中的元素组合 ⭐ 可替代max、min、sum等
(T,T) -> T, 不断reduce
collect 返回集合 collect策略有很多 —> ⭐ 可执行sum、average…等
最常见的collect就是Collectors.toList()策略, 就是将流转为一个List
类型归纳 — 转为集合容器 toXXX
Collectors.toList();
Collectors.toMap();
Collectors.toSet();
Collectors.toCollection();//含参构造,转化为new的容器
Collectors.toConcurrentMap();
分别将流转为List、Map、Set、Collection、 ConcurrentMap
joining 将元素用某规则连接起来
连接符号可以是delimiter连接符; 或者delimiter连接符、prefix开始符,suffix结束符; 除此之外,还可以空参,代表delimiter为空格
Collectors.joining(); // 以空格连接Collectors.joining("-"); //以-连接Collectors.joining("【",",","】"); //以【x, y, z.....】
collectingAndThen 先对结果进行归纳,之后再进行Function函数处理结果
结果操作就是将collect结果再执行
List<String> list = Arrays.asList("cfeng", "java", "数字大屏");
String str = list.stream().collect(Collectors.collectingAndThen(Collectors.joining(",","[","]"), s -> s + "你好")); System.out.println(str);
groupingBy 按照条件对结果分组
和SQL的group by类似,内存分组可以减少压力
比如
// 按照字符串长度进行分组 符合条件的元素将组成一个 List 映射到以条件长度为key 的 Map<Integer, List<String>> 中
servers.stream.collect(Collectors.groupingBy(String::length))
为了保证线程安全,可以采用安全的Map
Supplier<Map<Integer, Set<String>>> mapSupplier = () -> Collections.synchronizedMap(new HashMap<>());Map<Integer, Set<String>> collect = servers.stream.collect(Collectors.groupingBy(String::length, mapSupplier, Collectors.toSet()));
或者可以直接使用groupingByConcurrent
counting 对收集的结果求和
list.stream().count() 效果一样
list.sream().collect(Collectors.counting())
mapping(mapper, downSream) 在Collect中进行隐射
List<String> names = students.stream().collect(Collectors.mapping(Student::getName, Collectors.toList()));
maxBy(comparator)/minBy
大小元素的操作,和list.stream.max终端操作一样
list.stream().collect(Collectors.minBy(Comparator.comparingInt(String.length))) //字符串中比较按照长度比较list.stream().min(Comparator.comparingInt(String.length))
summingInt/Double/Long(元素 – 可用Lambda)
累加操作,和sum()终端操作一样
list.stream().collect(Collectors.summingInt(s -> s.length))) //字符串中比较按照长度比较list.stream().min(Comparator.comparingInt(String.length))
summarizingDouble/Int/Long⭐ 统计量: 包括总数 和 max/min 平均值
summarizing对应的就是统计量,会将总数、总和、max、min、avg等统计量提取出来放到IntSummaryStatisics
(Double、 Long) 等统计对象中
IntSummaryStatistics statistics = list.stream().collect(Collectors.summarizingInt(s -> s.length)));
需要的数据再从对象中直接取出即可
reducing ⭐ (T, T) -> T 元素两两比较淘汰一个(一轮轮reduce)
这个方法对用的终端操作也就是reduce
其参数为BinaryOperator< T》 , 给两个相同类型的量,返回一个同类型的结果, (T, T) -> T, 默认实现为maxBy和minBy, 也就是返回最大/小值, 元素两两比较根据给定的策略淘汰一个, 随着迭代的进行,元素reduce
下面是一个例子
//统计城市个子最高的人Comparator<Person> byHeight = Comparator.comparing(Person::getHeight); //子当以比较器为比较Person的身高Map<String, Optional<Person>> tallestByCity = people.stream().collect(Collectors.groupingBy(Person::getCity, Collectors.reducing(BinaryOperator.maxBy(byHeight))));