流的使用
1.筛选和分片
顾名思义就是运用一些列的方法对数据进行一个筛选,切分从而得到我们想要的数据内容
1.使用filter()进行筛选
list.stream().filter(apple -> "green".equals(apple5.getColor()))//筛选出绿色苹果
2.使用distinct()去除重复数据
List<Integer> list = Arrays.asList(2,3,4,2);
list.stream().filter(s->s%2==0).distinct().forEach(System.out::println);
3.使用limit()数据截取
List<Integer> list = Arrays.asList(2,3,4,2,6,8);
list.stream().filter(s->s%2==0)
.distinct()
.limit(3)
.forEach(System.out::println);
4.使用skip()跳过元素
List<Integer> list = Arrays.asList(2,3,4,2,6,8);
list.stream().filter(s->s%2==0)
.distinct()
.limit(3)
.skip(2)
.forEach(System.out::println);
2.映射
使用map(),和flatMap()从我们处理的对象中选取信息
1.使用map()处理流中的每一个元素,并将其映射成一个新的元素,这里需要注意的是,map()是重新创建一个新的元素,而不是对原来的元素进行修改
List<String> collect = list.stream()
.map(Apple::getName)//收集名字
.collect(Collectors.toList());//收集器进行收集
2.流的扁平化,使用map()能处理流里面的每一个元素,但是如果流里面的元素是一个数组呢,这个元素里面的每一元素都需要处理呢,那么这时候flatMap()就派上了用场,也许有人会问为什么不直接使用两此map()方法来处理这个返回的流呢,应为map()方法执行后返回的是一个流的列表举,个例子吧
List<String> list2 = Arrays.asList("HELLO","WORLD");
Stream<String[]> stream = list2.stream().map(s -> s.split(""));
我们要获取每一个单独的字符流,获取到的应该是 Stream,而不是 Stream<String[]>,所以我们需要将各个生成流扁平化成单个流进行处理,使用flatMap()的效果是,各个数组并不是映射成自己的一个流,而是映射成流里面的内容
List<String> list2 = Arrays.asList("HELLO","WORLD");
Stream<String> stringStream = list2.stream()
.map(s -> s.split("")).flatMap(Arrays::stream);
总而言之,flatMap()就是将流里面的每个值转化为另外的一个流,然将这个流给连起来,达到扁平化的目的.
3.查找和匹配
1.使用anyMatch() 返回一个boolean,所以这是一个终端操作
List<Integer> list1 = Arrays.asList(2,3,4,2,6,8);
System.out.println(list1.stream().filter(s->s%2==0)
.distinct()
.limit(3)
.anyMatch(s->s==2));
这里输出true
与之使用方法相同得还有 allMatch() 和 noneMatch()操作,这三个操作都是终端操作,会直接进行返回.
2.使用 findAnay()进行元素查找,通常结合filter()使用,会返回一个Optional,
Optional是Java8引入得一个容器类,如果没找到元素,容器里面会存在一个null,
从而避免一些直接操作null引发得空指针异常,Optional 里面得isPreasent()方法会判断里面是否存在值,放回true 或者false, get()方法用来取值
Optional<Integer> any1 = list1.stream().filter(s -> s % 8 == 0).findAny();
boolean present = any1.isPresent();
System.out.println(present);
Integer integer = any1.get();
System.out.println(integer);
如果你的过滤条件很多个元素都满足,只返回第一个
4.规约
1.使用 reduce()进行数字求和,reduce方法 接受两个参数第一个是初始值,第二个另外一个是 BinaryOperator 来将两个元素进行相关操作,而产生得新的值
List<Integer> list1 = Arrays.asList(2,3,4,2,6,8);
Integer reduce = list1.stream().reduce(0, (a, b) -> a + b);
System.out.println(reduce);
这里输出的是25
也可以使用 Integer的静态方法获取得到同样的值
List<Integer> list1 = Arrays.asList(2,3,4,2,6,8);
Integer reduce = list1.stream().reduce(0,Integer::sum);
System.out.println(reduce);
如果没有传入初始值的话,会返回 一个 Optional对象,应为不确定你操作的list里面是否存在值.
我们也能利用同样的方法来获取里面的最大值 和最小值
Integer reduceMax = list1.stream().reduce(0,Integer::max);
Integer reduceMin = list1.stream().reduce(0,Integer::min);
5.数值流
Java8引入了IntStream,DoubleStream和LongStream,分别将流的元素转化为int,double,long来解决代码中暗含的装箱成本的操作,例如这段代码里面就暗含的自动装箱拆箱的操作
int reduceMin = list1.stream().reduce(0,Integer::min);
1.映射到数值流,当一个流转化为数值常用的方法是mapToInt,mapToDouble,mapToLong,这些操作和map的使用方法都一样,只是会将这个流转换成特定的流例如:
int sum = list.stream().mapToInt(Apple::getNum).sum();
我们这里获取apple的数量的和,如果没有则返回0,IntStream还支持 min(),max(),average()等方法
2.数值流转换为对象流,应为数值流的操作具有一定的局限性,而转换成对象流,我们能有更多的操作空间,例如:我们需要把获取到的数值流的原始数放进一个对象里,这时我们就需要利用boxed()进行转换,转换成一般的流进行跟广义的操作
IntStream intStream = list.stream().mapToInt(Apple::getNum);
Stream<Integer> boxed = list.stream().mapToInt(Apple::getNum).boxed();
- 数值范围获取,在IntStream和LongStream里有range()和rangeClosed(),两个方法都是传入两个参数第一个方法传入起始值,第二个结束值,但不包含结束值,第二个方法接受两个参数,一个初始值,和结束值,包含结束值.
IntStream.range(1,10).forEach(System.out::println);
IntStream.rangeClosed(1,10).forEach(System.out::println);
总结一下,其实这些简单的函数组合在一起基本上能满足我们日常开发的简单实用,使用这些函数能大大的提高我们的开发效率.
资料来源<<Java8实战>>