23、Stream流

1、简介

管道

管道就是一系列的聚合操作。【聚合,即指对数据的整理和总结,如最大值,最小值等】
管道包含以下组件:
	(1)源:可以是集合,数组,生成器函数或I/O通道
	(2)零个或多个中间操作:诸如过滤器之类的中间操作产生新的流
	(3)终结操作:终端操作(例如forEach)会产生非流结果,例如原始值(如double),集合或者再在forEach的情况下根本没有任何值

流是一系列元素,与集合不同,它不是存储元素的数据结构。而是流通过管道携带来自源的值。
筛选器操作返回一个新的流,该流包含与筛选条件匹配的元素

2、如何获取流

(1)Collection接口

default Stream<E> stream();

(2)Stream接口

//获取流
public static<T> Stream<T> of(T....values);
//将两个流拼接成一个新的流
public static<T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b);

示例

public class StreamTest {

    public static void main(String[] args) {
        List<Integer> numbers1 = Arrays.asList(1, 2, 3, 4, 5);
        //获取一个流
        //集合接口
        Stream<Integer> s1 = numbers1.stream();

        //Stream接口
        Stream<Integer> s2 = Stream.of(6, 7, 8, 9, 10);

        //拼接
        Stream<Integer> s3 = Stream.concat(s1, s2);

        //Map接口
        Map<String, Integer> map = new HashMap<>();
        map.put("a", 1);
        map.put("b", 2);
        map.put("c", 3);
        map.put("d", 4);
        Stream<Map.Entry<String, Integer>> s4 = map.entrySet().stream();
    }
}

3、Stream流中间聚合操作

Stream接口

//根据给定的条件过滤流中的元素
Stream<T> filter(Predicate<? super T> predicate);
//将流中的元素进行类型转换
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
//去重
Stream<T> distinct();
//排序,如果存储元素没有实现Comparable或者相关集合没有提供Comparator将抛出异常
Stream<T> sorted();
//根据给定的上限,获取流中的元素
Stream<T> limit(long maxSize);
//跳过给定数量的元素
Stream<T> skip(long n);

//将流中元素全部转为整数
InStream mapToInt(ToIntFunction<? super T> mapper);
//将流中元素全部转为长整数
LongStream mapToLong(ToLongFuncation<? super T> mapper);
//将流中元素全部转为双精度浮点数
DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);

示例

public class AggregateOperation {

    public static void main(String[] args) {
        //传统方法
        List<Integer> nums = Arrays.asList(12, 3, 23, 54, 44);
        for (Integer n : nums) {
            if (n % 2 == 0) {
                System.out.println(n);
            }
        }

        //利用Stream流
        Stream<Integer> s1 = Stream.of(12, 3, 23, 54, 44);
//        Stream s2 = s1.filter(new Predicate<Integer>() {
//            @Override
//            public boolean test(Integer integer) {
//                return integer % 2 == 0;
//            }
//        });

        //Lambda表达式
        Stream<Integer> s2 = s1.filter(integer -> integer % 2 == 0);
        //打印元素
//        s2.forEach(System.out::println);
        //将流中的元素收集为一个List集合
        List<Integer> existNumbers = s2.collect(Collectors.toList());
        //将流中的元素收集为一个Set集合
        Set<Integer> set = s2.collect(Collectors.toSet());
        //将流中的元素收集为一个数组
//        Integer[] arr = s2.toArray(new IntFunction<Integer[]>() {
//            @Override
//            public Integer[] apply(int value) {
//                return new Integer[value];
//            }
//        });
        Integer[] arr = s2.toArray(Integer[]::new);
    }
}

4、Stream流终结操作

//遍历操作流中的元素
void forEach(Consumer<? super T> action);
//将流中元素按照给定转换方式转换为数组
<A> A[] toArray(IntFunction<A[]> generator);
//将流中的元素按照给定方式搜集起来
<R, A> R collect(Collector<? super T, A, R> collector);

//根据给定的排序方式获取流中的最小元素
Optional<T> min(Comparator<? super T> comparator);
//根据给定的排序方式获取流中的最大元素
Optional<T> max(Comparator<? super T> comparator);
//获取流中发第一个元素
Optional<T> findFirst();

//获取流中的元素个数
long count();
//检测流中是否存在给定条件的元素
boolean anyMatch(Predicate<? super T> predicate);
//检测流中是否全部满足给定条件
boolean allMatch(Predicate<? super T> predicate);
//检测流中元素是否全部不满足给定条件
boolean noneMatch(Predicate<? super T> predicate);

5、Stream流聚合操作与迭代器的区别

官方文档

聚合操作(如forEach)似乎像迭代器,但是,它们有几个本质区别:
	(1)聚合操作使用内部迭代:聚合操作不包含诸如next的方法来指示它们处理集合的下一个元素。而是使用内部委托,你的程序确定要迭代的集合,而JDK确定如何迭代该集合。
	而通过外部迭代,你的应用程序既可以确定要迭代的集合,又可以确定迭代的方式,但是外部迭代只能顺序地迭代集合的元素,内部迭代没有此限制。
	内部迭代可以更轻松利用并行计算的优势,这涉及将问题分为子问题,同时解决这些问题,然后将解决方案的结果组合到子问题中。
	(2)聚合操作从流中而不是直接从集合中处理元素,因此,它们也称为流操作
	(3)它们支持将i行为作为参数,可以将lambda表达式指定为大多数聚合操作的参数,这使你可以自定义特定聚合
posted @ 2022-03-08 23:56  DarkSki  阅读(87)  评论(0编辑  收藏  举报