Java Stream流处理
1.Stream的概念Stream是一组用来处理数组.集合的API好处:1. 代码简洁意图明确使用Stream接口让你从此告别for循环2. 多核友好,函数式编程使得并行程序如此简单你需要的全部就是调用一下parallel()方法处理集合非常方便2.Stream的特点1. 不是数据结构,没有内部存储在一套执行操作中,中间的某个操作不会存储数据2. 不支持索引访问例如一个int[] i = {1,
·
1.Stream的概念
Stream是一组用来处理数组.集合的API 好处: 1. 代码简洁 意图明确 使用Stream接口让你从此告别for循环 2. 多核友好,函数式编程使得并行程序如此简单 你需要的全部就是调用一下parallel()方法 处理集合非常方便
2.Stream的特点
1. 不是数据结构,没有内部存储 在一套执行操作中,中间的某个操作不会存储数据 2. 不支持索引访问 例如一个int[] i = {1,2,3,4}; 的数组,在操作中不能再使用i[0]获取0位置这种索引查找数据的操作 3. 延迟计算 这是一个懒执行过程,只有在一套流操作触发执行操作才会执行,之前的操作在没有触发执行之前不执行 4. 支持并行 5. 很容易生成数组或者集合 (List,Set) 6. 支持过滤,查找,转换,汇总,聚合等操作
3.Stream运行机制
三个条件: 源source,中间操作,终止操作
一定要牢记这三个条件,至关重要的作用
1. 源source: 可以是一个数组,一个集合,一个生成器方法,一个I/O通道
2. 中间操作: 一个流可以有0个或者多个中间操作,每个中间操作都会返回一个新的流,供下一个使用,一个流只会有一个终止操作
3. 终止操作: Stream只有遇到终止操作,它的源才开始进行中间操作 在stream中,集合元素就是每一个元素作为stream处理的粒度,数组元素以每个下标位置的数据作为一个粒度
4.生成source的方式
1. 通过数组来生成 int[] i = {1,2,3,4}; Stream<int[]> stream = Stream.of(i); //不受类型约束,char也行 或者 int[] i = {1,2,3,4}; Arrays.stream(); //这种方式生成的流会受类型的限制 用户自定义类型可以,int long double都可以其余的不行例如char 2. 通过集合来生成 List<Integer> list = Arrays.asList(1,2,3,4,5,6); Stream<Integer> stream = list.stream(); 3. 通过generate生成 Stream<Integer> generate = Stream.generate(() -> 1); //generate实现了接口Spliterator接口,将lambda表达式的返回值生成source 4. 通过迭代器生成 Stream<Integer> iterate = Stream.iterate(1, x -> x + 1); iterate(1, x -> x + 1) == iterate(1, (x) -> {return x + 1;})简化了 5. 其他API创建 String s = "snanca"; IntStream stream = s.chars(); //常用的一般也就是1,2
5.中间操作
如果调用方法以后的返回结果是一个Stream对象,就意味着是一个中间操作 1. filter 过滤,将符合条件的元素传入下一个流,不符合的过滤掉 //返回一个Stream 如果是一个IntStream返回IntStream 2. mapToInt 将一个stream转换成IntStream 3. sorted 按照自然序排列,可以通过lambda表达式传入比较器 4. distinct 去重 //去重还可以使用终止操作 collect(Collectors.toSet()) 5. map 原数组集合的加工,映射成一对一映射的新数组
6.终止操作
1. 计算: max min count average //max min,传入一个lambda 定义比较策略 返回值Optional 返回最大值,最小值封装在Optional对象 //count 返回的是数据的数量,这个并不是数据的总加和 2. 匹配 findAny //可以自由选择流中的任何元素 findFirst //返回OptionalInt描述此流的第一个元素 anyMatch //匹配的某一个 allMatch //匹配的全部 3. 收集器 toArray //返回一个数组 collect //将流中数据返回一个集合对象 需要传入一个定义转换的工具方法 例: Collectors.toList() 4. 循环 forEach 5. 汇聚 reduce
7.Optional
在终止操作中,很多的方法返回值都是Optional类型,这个也是之前我自己不怎么了解的地方 Optional 类是一个可以为null的容器对象,Optional 类的引入很好的解决空指针异常。 在Stream中引入这个作为返回值的好处在于不会在终止条件处理时报出空指针异常,让我们在写Stream流时无需关注空指针问题 在Stream处理完以后返回Optional对象,又我们自己进行可控的空指针处理或者取值操作例: Person s1 = new Person("wang",12); Person s2 = new Person("zhang",78); Person s3 = new Person("duan",13); List<Person> list = new ArrayList<>(); list.add(s1); list.add(s2); list.add(s3); Optional<Person> max = list.stream().filter((x) -> { if (x.name == "wang") { x.name = "xxoo"; } return true; }).max((x1, x2) -> x1.age - x2.age); boolean present = max.isPresent(); System.out.println(max.get().name);
Java 8 Optional 类 | 菜鸟教程 (runoob.com)这里有比较完整的Optional介绍
8.常用技巧及方法选择
构造对象
这里是lambda自己写demo时候不太清楚的地方,可以不用看
class Person{ String name; public Person(String name) { this.name = name; } public static Person build(String name) { return new Person(name); } } public static void main(String[] args) { Stream.of(str.split(",")).map(x -> new Person(x)); //正常写法 Stream.of(str.split(",")).map(Person::new); //传入的数据默认作为new的参数 Stream.of(str.split(",")).map(Person::build); //传入的数据默认作为build静态方法的参数 //这些写法都是lambda表达式的写法 } }
map和filter的选择
map方法对数据进行加工,加工完进行全量返回 filter方法既可以进行数据的过滤也可以在里面进行加工,但是filter实现的接口返回值是一个boolean,也就是一个过滤操作,既然是一个返回值boolean,那么只要返回值都是true,自然也不会进行过滤操作,数据全量返回 所以在API的选择时,很多都是相似的,只不过为了解耦我们更希望对应的API做对应的事情,很容易维护 map和filter使用顺序和情况: 可以先使用map进行数据处理,在使用filter进行数据过滤 也可以先进行filter,在进行map数据处理 这种情况是在每数据处理之前就能筛选出来想要的数据 还可以在filter即处理数据又进行过滤,完成map的功能
Person s1 = new Person("wang");
Person s2 = new Person("zhang");
Person s3 = new Person("duan");
List<Person> list = new ArrayList<>();
list.add(s1);
list.add(s2);
list.add(s3);
List<Person> listResult = list.stream().filter((x) -> {
if (x.name == "wang") {
x.name = "xxoo";
}
return true;
}).collect(Collectors.toList());
for (Person x:listResult) {
System.out.println(x.name);
}
结果:
xxoo
zhang
duan
//这个例子就是将所有的filter返回都设置为true,那么处理的结果也都全量返回了
更多推荐
所有评论(0)