学习笔记-Stream

是什么?

流,支持顺序和并行聚合操作的一系列元素。是一个操作,一个动作action。

有什么用?

对数据源(数组或集合)进行操作,产生新的数据。能高效便利的操作集合(collection)对象。适用于操作大批量数据。

数据源
批量操作
结果

怎么用?

1. 创建Stream

//collection流,通过Collection的stream()获得
       List<String> list = new ArrayList<>();
       Stream<String> stream = list.stream();

       //数组流,通过Arrays.stream()静态方法获得
       int[] count = new int[10];
       count[0] = 1;
       count[1] = 2;
       count[3] = 3;
       count[2] = 4;
       count[4] = 5;
       count[5] = 6;
       IntStream stream1 = Arrays.stream(count);
       IntStream stream2 = Arrays.stream(count, 1, 5);
       stream2.forEach(System.out::println);

       //Stream.of()静态方法获得
       Stream<String> stringStream = Stream.of("abc");
       Stream<String> stringStream1 = Stream.of("abc", "def");
       stringStream1.forEach(System.out::println);
       //该方法调用Arrays.stream("abc", "def");


       //无限流,Stream.iterate()静态方法获得,
       Stream<String> stream3 = Stream.iterate("Lambda", (x) -> x + "->method reference");
       //stream3.forEach(System.out::println);//Lambda的基础上不断地加->method reference
       /*Lambda
       Lambda->method reference
       Lambda->method reference->method reference
       Lambda->method reference->method reference->method reference
       Lambda->method reference->method reference->method reference->method reference
       Lambda->method reference->method reference->method reference->method reference->method reference
       .....*/
       //stream3.limit(12).forEach(System.out::println);//需要用limit指定输出大小,否则会无限输出
       Stream<Integer> iterate = Stream.iterate(0, (x) -> x + 1);
       iterate.limit(10).forEach(System.out::println);
       //无限流,Stream.generate()静态方法创建
       Stream.generate(() -> "return").limit(3).forEach(System.out::println);

       //基本数据类型流
       IntStream.range(1, 5).forEach(System.out::println);
       LongStream.range(1, 6).forEach(System.out::println);
       //range(),创建从第一个参数到第二个参数的有序流,以1的步长递增后续元素的值,不包括最后一个元素

       //字符串的流
       IntStream chars = "after".chars();
       chars.forEach(System.out::print);

2. 流操作

操作并不会改变原始数据,但会产生一个新的流,且如果不对产生的新流进行终端操作,该流不会有任何输出。流操作可以没有。
(1) 筛选 filter
从流中筛选元素

public interface Stream<T> extends BaseStream<T, Stream<T>> {
    Stream<T> filter(Predicate<? super T> predicate);
    //参数为断言接口,可以用lambda表达式

示例:

//数组流,通过Arrays.stream()静态方法获得
        int[] count = new int[10];
        count[0] = 1;
        count[1] = 2;
        count[3] = 3;
        count[2] = 44;
        count[4] = 56;
        count[5] = 66;
        IntStream stream2 = Arrays.stream(count, 1, 5);
        //stream2.forEach(System.out::println);执行此代码后不可以执行中间操作
        IntStream intStream = stream2.filter((x) -> {System.out.println("是否大于3");return  x > 3;});
        //中间操作会返回一个新流。
        //如果在中间操作之前执行过终端操作(如forEach)则不可以执行中间操作。
        intStream.forEach(System.out::println);

(2) 截断流 limit
使元素不超过给定数量

		Stream<T> limit(long maxSize);

示例:

List<String> list = new ArrayList<>();
        list.add("aa");
        list.add("ee");
        list.add("cc");
        list.add("dd");
        Stream<String> stream = list.stream();
        stream.limit(2).forEach(System.out::println);//aa ee

(3) 跳过元素 skip

		Stream<T> skip(long n);

示例:

List<String> list = new ArrayList<>();
        list.add("aa");
        list.add("ee");
        list.add("cc");
        list.add("dd");
        Stream<String> stream = list.stream();
        stream.skip(2).forEach(System.out::println);//cc dd

(4) 去重 distinct
通过流生成元素的hashCode()和equals()去除重复元素。
对于对象来说要重写hashCode()和equals()才会去重成功

    	Stream<T> distinct();

示例:

List<String> list = new ArrayList<>();
        list.add("aa");
        list.add("aa");
        list.add("aa");
        list.add("aa");
        Stream<String> stream = list.stream();
        stream.skip(2).forEach(System.out::println);//cc dd

(5) 映射 map
以函数为参数,将每个元素都以函数作用之后返回一个新元素 。

    	<R> Stream<R> map(Function<? super T, ? extends R> mapper);
    	//以函数接口为参数。Function,接收一个参数,返回一个类型。

示例:

		List<String> list = new ArrayList<>();
        list.add("aa");
        list.add("aa");
        list.add("aa");
        list.add("aa");
        Stream<String> stream = list.stream();
        stream.map((x) -> x.toUpperCase() + "小写变大写").forEach(System.out::println);

(5) 映射 flatMap
以函数为参数,将每个元素都以函数作用之后返回一个新流,再将每个元素产生的流拼接成一个流 。

    	<R> Stream<R> map(Function<? super T, ? extends R> mapper);
    	//以函数接口为参数。Function,接收一个参数,返回一个类型。

示例:

		public class StreamTest {
		    @Test
		    public void TestStream(){
		        List<String> list = new ArrayList<>();
		        list.add("aa");
		        list.add("aa");
		        list.add("aa");
		        list.add("aa");
		        Stream<String> stream = list.stream();

				stream.flatMap(StreamTest::toStream).forEach(System.out::println);
				//使用flatMap可以达到以下两行代码的效果
		        //Stream<Stream<Character>> streamStream = stream.map(StreamTest::toStream);
		        //此时中间操作返回一个流 (包含着很多流)
		        //streamStream.forEach((x) -> x.forEach(System.out::println));    }
		
		    //传入字符串返回一个流
		    public static Stream<Character> toStream(String string) {
		        List list = new ArrayList<>();
		        for (Character ch : string.toCharArray()) {
		            //String -> char[]
		            list.add(ch);//将每个Character存入List中            
		        }
		        Stream stream = list.stream();
		        return stream;
		    }
		}

(6) 自然排序 sorted

		    Stream<T> sorted();

示例:

		List<String> list = new ArrayList<>();
        list.add("abcde");
        list.add("ab");
        list.add("abcd");
        list.add("abc");
        Stream<String> stream = list.stream();
        stream.sorted().forEach(System.out::println);
        //ab
		//abc
		//abcd
		//abcde

(7) 定制排序 sorted(Comparator com)

    	Stream<T> sorted(Comparator<? super T> comparator);

示例:

			List<String> list = new ArrayList<>();
	        list.add("abcde");
	        list.add("ab");
	        list.add("abcd");
	        list.add("abc");
	        Stream<String> stream = list.stream();
	        stream.sorted((e, x) -> {
	            if (e.length() < x.length()) {
	                return 1;
	            }else
	            {
	                return -1;
	            }
	     	 }).forEach(System.out::println);
	     	 //abcde
			 //abcd
			 //abc
			 //ab

3. 终端操作

创建流后可以直接执行终端操作。

  1. allMatch 检查是否匹配所有元素
		boolean allMatch(Predicate<? super T> predicate);

  1. anyMatch 检查是否匹配至少一个元素
		boolean anyMatch(Predicate<? super T> predicate);
  1. noneMatch Z检查是否没有匹配所有元素
		boolean noneMatch(Predicate<? super T> predicate);
  1. findFirst 返回第一个元素
		Optional<T> findFirst();

示例:

List<String> list = new ArrayList<>();
        list.add("abcde");
        list.add("ab");
        list.add("abcd");
        list.add("abc");
        Stream<String> stream = list.stream();
        Optional<String> first = stream.findFirst();
        System.out.println(first.get());//
  1. findAny 返回当前流的任意一个元素
		Optional<T> findAny();
  1. count 返回流中元素的总个数
		long count();
  1. max 返回流最大值
		Optional<T> max(Comparator<? super T> comparator);
  1. min 返回流最小值
		Optional<T> min(Comparator<? super T> comparator);

示例:

		 Optional<String> max = stream.min((x, y) -> {
            if (x.length() > y.length()) {
                return 1;
            } else {
                return -1;
            }
        });
        System.out.println(max.get());//ab
  1. reduce 归约
		T reduce(T identity, BinaryOperator<T> accumulator);
		//指定初始值,并对流内元素进行累加操作,返回值一定不为空
		Optional<T> reduce(BinaryOperator<T> accumulator);
		//返回值可能为空,所以返回Optional
		 <U> U reduce(U identity,
                 BiFunction<U, ? super T, U> accumulator,
                 BinaryOperator<U> combiner);

示例:

		List<String> list = new ArrayList<>();
        list.add("abcde");
        list.add("ab");
        list.add("abcd");
        list.add("abc");
        Stream<String> stream = list.stream();
        String reduce = stream.reduce("0", (x, y) -> x + y);
        System.out.println(reduce);
        //0abcdeababcdabc
  1. collect 收集
		<R> R collect(Supplier<R> supplier,
                  BiConsumer<R, ? super T> accumulator,
                  BiConsumer<R, R> combiner);
                  
	       <R, A> R collect(Collector<? super T, A, R> collector);
	       //Collector是一个接口是一个收集器,该接口有一个实现类:Collectors提供很多静态方法,

示例:

		List<Student> list = new ArrayList<>();
        list.add(new Student("张三", 12, "秦国", "学习中"));
        list.add(new Student("李四", 13, "楚国", "缀学"));
        list.add(new Student("王五", 15, "晋国", "学习中"));
        list.add(new Student("赵六", 16, "赵国", "缀学"));
        Stream<Student> stream = list.stream();
        HashSet<String> collect = stream.map(Student::getName).collect(Collectors.toCollection(HashSet::new));
        collect.forEach(System.out::println);	     

补充知识

Optional 对象

是一个容器对象,可以包含也可以不包含非null值。个人理解是一个包装类,可以将类进行包装,能避免空指针异常。

		Optional<Object> empty = Optional.empty();
        //获取空的Optional对象
        Optional<Student> stuOp = Optional.ofNullable(new Student());
        Optional<Student> stuOp1 = Optional.of(new Student());
        //获取Optional对象
        //of与ofNullable区别:两者方法传入参数为null时,of方法会报错,而ofNullable不会报错。

        Student student = stuOp.get();
        //获取Optional封装的对象

        Student s  = new Student("zs", 1, "齐国", "学习中");
        stuOp.orElse(s);
        stuOp1.orElseGet(Student::new);
        //Optional不为空返回包含值,为空返回形参。
        //区别: orElseGet操作空间更大。且当Optional不为空时不会执行orElseGet方法,而orElse不论Optional是否为空都执行。

        boolean present = stuOp.isPresent();
        //判断Optional对象是否为空

        Optional<Student> stu = Optional.ofNullable(s);
        System.out.println(stu.map((y) -> y.getName()).get());

        System.out.println(stu.flatMap((y) -> Optional.of(y.getName())).get());
        //对Optional进行处理,处理结果有值时返回新的Optional,无值返回Optional.empty()
        //区别:方法 形参的返回值 不同,flatMap形参返回必须是Optional;
        //Optional在存在始终牵着Null的手

Fork/Join框架

将一个大任务拆分为多个小任务,然后将小任务的执行结果进行汇总。当数据量庞大时适合使用。

并行流

把一个流的内容拆分为多个数据块,使用多个线程分别处理每个数据块的流。并行流内部使用的是Fork/Join框架。在Stream中可以使用parallel() 和 sequential() 进行并行和顺序的转换。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值