java8 Steam流及Optional的使用
前言:综合了一下常用Stream流与Optional操作,底部有本人常用的Stream流判空写法,用以记录和复习
Stream流:
获取流
1. list获取:
List<String> list= new ArrayList(); Stream<String> stream=list.stream();
- set
Set<String> set=new HashSet<>() Stream<String> stream=set.stream();
- vector
Vector<String> vector = new Vector<>(); Stream<String> stream = vector.stream();
2. Map获取
需要分key、value或entry等情况
Map<String, String> map = new HashMap<>();
//key
Stream<String> keyStream = map.keySet().steam();
//value
Stream<String> valueStream = map.values().stream();
//entry
Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream();
3. 数组获取
数组不能添加默认方法,Stream中提供静态方法of
String[] array = {"张三","李四","王五","赵六" };
Stream<String> stream = Stream.of(array);
//或使用Arrays的静态方法
Arrays.stream(array)
}
流方法分类:
- 延迟方法
支持链式调用,
返回值类型仍然是 Stream 接口自身类型的方法
- 终结方法
不支持类似 StringBuilder 那样的链式调用,
返回值类型不再是 Stream 接口自身类型的方法
1. forEach(终结方法)
list.stream.foreach(h->{System.out.println(s)});
2. count计数(终结方法)
返回值为long
list.stream().count();
3.filter过滤
将一个流转换成另一个子集流
//删选stream中名字首字为方的 list.stream().filter(user->{user.startWith("方")});
4.limit截取
参数是一个long型,如果集合当前长度大于参数则进行截取;否则不进行操作
list.stream().limit(3);
5.skip跳过
流的当前长度大于n,则跳过前n个;否则将会得到一个长度为0的空流
list.stream.skip(2);
6.map映射
可转换不同流类型(可自动装箱)
Stream<String> original = Stream.of("1", "2", "3"); Stream<Integer> result = original.map(s->Integer.parseInt(s));
7.concat组合
将两个流合并为一个流
注:此为静态方法,与
java.lang.String
中的concat有区别Stream.concat(streamA, streamB);
8.distinct去重
distinct不光通过值,还比较地址进行去重
list.stream().distinct();
9.faltMap扁平化流
CSDN大佬解释通俗易懂:
//(map)流中有流,需要两次遍历 Stream<Stream<Character>> streamStream = list.stream().map(StreamDemo::fromStringToStream); streamStream.forEach(s -> { s.forEach(System.out::println); }); //(flatMap)流里还有流,使用flatMap可以直接把里面的流打开,一次遍历就可以了 Stream<Character> characterStream = list.stream().flatMap(StreamDemo::fromStringToStream); characterStream.forEach(System.out::println);
10. sort排序
- 默认为自然排序 :
list.stream.sorted()
- 定制排序
需要传入Comparator接口(如果流中的是引用类型,只能用定制排序)
//常规: integerList.stream() .sorted((e1,e2) -> e2->e1) .forEach(System.out::println); //集合中根据对象属性排序 List<User> list=new ArrayList<>(); list.stream() .sorted(Comparator.comparing(User::getAge)) .collect(Collectors.toList());
11.match 检测匹配(终结方法)
返回为Boolean值
//1.allMatch 全部匹配--判断列表中是否全大于5 list.stream().allMatch(i -> i > 5) //2.anyMatch 至少匹配 --判断列表值是否至少有一个大于5 list.stream().anyMatch(i -> i > 5) //3.noneMatch 没有匹配 --判断列表值是否全部不大于5 list.stream().noneMatch(i -> i > 5)
12.查找
findFirst 查找第一个元素,返回Optional
findAny 查找任意元素 返回Optional
list.stream.findFirst(); list.stream.findAny();
- max 查找最大最小值(终结方法) 返回Optional
// 查找最大的数 list.stream().max((e1, e2) -> e1 - e2);
13. reduce 缩减(终结方法)
实现 求和,求积,求最大值
//求和 list.stream().reduce((x, y) -> x + y) list.stream().reduce(0,Integer::sum) //求积 list.stream().reduce((x,y)->x*y) //求最大值 list.stream().reduce((x, y) -> x > y ? x : y) list.stream().reduce(1, Integer::max)
14.collect 收集(终结方法)
流转换
//toList 返回偶数集合 list.stream().filter(x -> x % 2 == 0).collect(Collectors.toList() //toSet返回Set集合 list.stream().collect(Collectors.toSet()) //toMap返回Map ---user中有name,age List<User> userList= new ArrayList<User>(); list.stream().collection(Collectiors.toMap(User::getName,user->user)
15 迭代 Stream.iterate
使用Stream.iterate创建流,即无限流
//生成一个0-4的自增数,并打印输出
Stream.iterate(0, n -> n + 1)
.limit(5)
.forEach(x -> System.out.println(x));
使用流注意点:
程序猿大佬链接:java成神之——Stream和Optional
1. 如果一个流没有调用终端方法,那么流的其他操作都不会执行。
2. 流用来操作文件的时候才需要手动关闭,单独使用Stream不需要关闭
try (Stream<String> lines = Files.lines(Paths.get("C:\Users\stream.txt")).onClose(() -> System.out.println("流自动关闭"))) { lines.forEach(System.out::println); }
3. 平行流:.parallelStream()
list.parallelStream().forEach(System.out::println);
注:如果对元素的顺序不要求的时候可以使用平行流,开启多核心多线程加速处理速度,使用平行流会显著降低性能
4. 流本身是不能重用的,但是可以使用iterator来实现重用
5. 分组计数:
Stream
.of("a", "b", "a", "c")
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.forEach(System.out::println);
a=2
b=1
c=1
Optional操作
CSDN大佬博客:
通常用以解决空指针异常:
方法 | 使用描述 |
---|---|
of | 把指定的值封装为Optional对象,如果指定的值为null,则抛出NullPointerException |
empty | 创建一个空的Optional对象 |
ofNullable | 把指定的值封装为Optional对象,如果指定的值为null,则创建一个空的Optional对象 |
get | 如果创建的Optional中有值存在,则返回此值,否则抛出NoSuchElementException |
orElse | 如果创建的Optional中有值存在,则返回此值,否则返回一个默认值 |
orElseGet | 如果创建的Optional中有值存在,则返回此值,否则返回一个由Supplier接口生成的值 |
orElseThrow | 如果创建的Optional中有值存在,则返回此值,否则抛出一个由指定的Supplier接口生成的异常 |
filter | 如果创建的Optional中的值满足filter中的条件,则返回包含该值的Optional对象,否则返回一个空的Optional对象 |
map | 如果创建的Optional中的值存在,对该值执行提供的Function函数调用 |
flagMap | 如果创建的Optional中的值存在,就对该值执行提供的Function函数调用,返回一个Optional类型的值,否则就返回一个空的Optional对象 |
isPresent | 如果创建的Optional中的值存在,返回true,否则返回false |
ifPresent | 如果创建的Optional中的值存在,则执行该方法的调用,否则什么也不做 |
常用方式:
方式一(不建议使用Optional进行集合判空,集合判空使用CollectionUtil)
List<String> list=new ArrayList<>();
//正确方式
if (CollectionUtil.isNotEmpty(list)) {
list.stream().forEach(h ->
System.out::println
);
System.out.println(list)
}
//(不推荐)出现问题:
//在new List时,Optional在判断list的size=0进行sql操作时可能会出现问题
Optional.ofNullable(list).ifPresent(list -> {
list.stream().forEach(进行sql 操作);
});
方式二
//返回一个新的空对象
Optional.ofNullable(userList).orElseGet(() -> {
return new ArrayList<>();
})
.stream()
.filter(a -> a != null)
.forEach(System.out::println);
}
//过滤list中值为空的数,同样使用list不推荐,
//最好使用CollectionUtils进行集合判空后使用
Optional.ofNullable(list).ifPresent(ll -> {
ll.stream()
.filter(a -> a != null)
.forEach(h ->System.out::println);
});