java stream操作 Stream是什么 Stream又称为流,可以将集合转换为一种流,对集合中的每个元素进行一系列的流式操作,流并不存储元素,对流的操作也不会修改数据源
数据源 ———转换为—》流——》进行中间操作——》终止操作
多个中间操作可以连接起来形成一个流水线,除非流水线触发终止操作,否则中间操作不会执行任何处理,在终止操作时一次性全部处理
转化为流 使用stream()或者parallelStream()方法将集合转为流
生成流 可以使用Stream.generate来生成流,产生一个无限流,通过反复调用函数来生成流
1 Stream<String> stream = Stream.generate(()->"Echo" );
也可以使用Stream.of来生成Stream,产生一个给定值的流
1 Stream<String> stream1 = Stream.of("hello" , "java8" );
可以用Stream.empty生成一个不包含任何元素的流
1 Stream<Object> empty = Stream.empty();
可以使用Arrays.stream根据数据来生成流
1 Stream<String> stream2 = Arrays.stream(new String[]{"hello" , "java8" });
中间操作 中间操作是惰性求值的,只进行描述Stream,而不产生新的集合
筛选 filter 过滤操作,只返回为true(满足Predicate断言条件)的数据
1 2 Stream<T> filter (Predicate<? super T> predicate) ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public static void testFilter () { Stream<String> stream = list.stream() .filter(e -> { System.out.println("filter中间操作" ); return e.equals("张三" ); } ); System.out.println("----中间操作结束----" ); stream.forEach( System.out::println ); }
distinct 去重
1 2 3 4 5 6 public static void testDistinct () { list.stream().distinct().forEach(System.out::println); }
切片 limit 返回前n个元素
1 2 3 4 5 6 public static void testLimit () { list.stream().limit(2 ).forEach(System.out::println); }
skip 去除(跳过)前n个元素
1 2 3 4 5 6 public static void testSkip () { list.stream().skip(2 ).forEach(System.out::println); }
1 2 3 4 5 6 public static void testLimitAndSkip () { System.out.println("--------先limit再skip---------" ); list.stream().limit(2 ).skip(1 ).forEach(System.out::println); System.out.println("--------先skip再limit---------" ); list.stream().skip(1 ).limit(2 ).forEach(System.out::println); }
注意:在limit和skip搭配使用的时候,两个的顺序不同会导致结果不同
先进行limit,再进行skip时,会选择前两个数据,然后再跳过第一个数据,只会筛选出一条数据
先进行skip,再进行limit时,会先跳过一条数据,在选择剩下数据的前两条,最终会筛选出两条数据
排序 sorted 排序可以有两种排序方式,第一种是进行排序的类要实现Comparable接口,第二种是在自己实现一个Comparator接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public static void test () { list.stream().map(User::getAge).sorted().forEach(System.out::println); } public static void test1 () { list.stream().sorted( (o1, o2) -> { if (o1.getAge() > o2.getAge()){ return -1 ; } return 0 ; } ).forEach(System.out::println); }
映射 map 转换功能,将mapper应用于当前流中的所有元素所产生的结果,其将一种类型的值转换成了另一种类型
1 2 <R> Stream<R> map (Function<? super T, ? extends R> mapper) ;
1 2 3 4 5 6 7 8 9 10 public static void testMap () { list.stream().map(User::getAge).forEach(System.out::println); }
flatmap 将多个Stream合并成一个Stream,将mapper应用于当前流中所有元素所产生的结果连接到一起(每一个结果都是一个流)
1 2 <R> Stream<R> flatMap (Function<? super T, ? extends Stream<? extends R>> mapper) ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public static void testFlatMap () { List<String> add = new ArrayList<>(); add.add("添加元素" ); List<String> strings = list.stream().map(User::getName).collect(Collectors.toList()); strings.stream().flatMap( TestStreamApi1::joinStream ).forEach(System.out::println); }
终止操作 allMatch 流中所有元素都要匹配给定的条件为true,否则为false 相当于且
1 2 3 4 5 6 7 8 9 public static void testAllMatch () { boolean isSex = list.stream().allMatch( l -> l.getSex() == 0 ); System.out.println(isSex); }
anyMatch 流中有任意一条数据匹配给定的条件为true,否则为false 相当于并
1 2 3 4 5 6 7 8 9 public static void testAnyMatch () { boolean isSex = list.stream().anyMatch( l -> l.getSex() == 0 ); System.out.println(isSex); }
noneMatch 流中所有的数据都不匹配给定条件时为true,否则为false 相当于非
1 2 3 4 5 6 7 8 9 public static void testNoneMatch () { boolean isSex = list.stream().noneMatch( l -> l.getSex() == 0 ); System.out.println(isSex); }
findFirst 找到第一个元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public static void testFindFirst () { User user = list.stream().sorted( ((o1, o2) -> { if (o1.getAge() > o2.getAge()){ return -1 ; } else if (o1.getAge() < o2.getAge()){ return 1 ; } return 0 ; }) ).findFirst().get(); System.out.println(user); }
findAny 找到其中任意一个元素
1 2 3 4 5 6 7 8 9 public static void testFindAny () { User user = list.stream().filter( l -> l.getSex() == 0 ).findAny().get(); System.out.println(user); }
count 返回流中元素的数量
1 2 3 4 5 6 7 public static void testCount () { long count = list.stream().count(); System.out.println(count); }
max 返回流中根据比较之后的最大值元素
1 2 Optional<T> max (Comparator<? super T> comparator) ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public static void testMax () { User user = list.stream().max( ((o1, o2) -> { if (o1.getAge() > o2.getAge()){ return 1 ; } else if (o1.getAge() < o2.getAge()){ return -1 ; } return 0 ; }) ).get(); System.out.println(user); }
min 返回流中根据比较之后的最小值元素
1 2 Optional<T> min (Comparator<? super T> comparator) ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public static void testMin () { User user = list.stream().min( ((o1, o2) -> { if (o1.getAge() > o2.getAge()){ return 1 ; } else if (o1.getAge() < o2.getAge()){ return -1 ; } return 0 ; }) ).get(); System.out.println(user); }
归约和收集 归约reduce 使用reduce来进行运算,从一组值中生成一个值
像count()、max()、min()、sum()这些内部其实也是使用的reduce
1 2 Optional<T> reduce (BinaryOperator<T> accumulator) ;
1 2 3 4 5 6 7 8 9 10 11 12 public static void testReduce () { List<Integer> list = Arrays.asList(1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ); int sum = list.stream().reduce((x, y) -> x+y).get(); System.out.println(sum); }
收集collect 根据不同的收集器collect(Collectors.toList())、collect(Collectors.toSet())来返回不同的集合
1 2 3 4 5 6 7 8 public static void testCollect () { List<String> strings = list.stream().map(User::getName).collect(Collectors.toList()); System.out.println(strings); }
数据汇总 使用summingInt可以获取总和
1 2 Integer sum = list.stream().collect(Collectors.summingInt(User::getAge)); System.out.println(sum);
使用averagingInt可以计算平均值
1 2 Double average = list.stream().collect(Collectors.averagingInt(User::getAge)); System.out.println(average);
使用summarizingInt可以获取个数、总和、平均值、最大值和最小值
1 2 3 IntSummaryStatistics summaryStatistics = list.stream().collect(Collectors.summarizingInt(User::getAge)); System.out.println(summaryStatistics);
连接字符串 joining用于连接字符串
1 2 String join = list.stream().map(User::getName).collect(Collectors.joining("," )); System.out.println(join);
数据分组 collect还可以对数据进行分组
1 2 Map<Long, List<Long>> collect = adUnits.stream().collect(Collectors.groupingBy(AdUnit::getAd_campaign_id, Collectors.mapping(AdUnit::getId, Collectors.toList())));
groupingBy收集器接受一个分类函数,用来对数据分组
数据分区 partitioningBy用于数据分区
1 2 3 4 Map<Boolean,List<User>> join = list.stream().collect(Collectors.partitioningBy(user -> user.getSex() == 0 )); System.out.println(join);
分区就是分组的一个特殊情况
Optional的使用 当初java8打着去除空指针的旗号推出了Optional,但是很多人用起来发现其实和判断是否为null没什么区别
其实有效地使用Optional的关键是要使用这样的方法:它的值不存在的情况下产生一个可替代物,而只有在值存在的情况下才会使用这个值
1 2 3 4 5 6 7 8 9 10 public T orElse (T other) public T orElseGet (Supplier<? extends T> other) public <X extends Throwable> T orElseThrow (Supplier<? extends X> exceptionSupplier) throws Xpublic void ifPresent (Consumer<? super T> consumer) public <U> Optional<U> map (Function<? super T, ? extends U> mapper)
而对于有些人总是使用optional.isPresent()来判断是不是空,其实和之前判断value != null没什么区别,这种情况使用Optional没有任何好处