java8 stream流入门

      学习流之前建议先学习lambda表达式的应用。

1.流简介

    Stream的优点:声明性,可复合,可并行。这三个特性使得stream操作更简洁,更灵活,更高效。

    Stream的操作有两个特点:可以多个操作链接起来运行;内部迭代;

    集合和流的区别:集合包含目前的所有元素,你要什么就去集合里取。流是你要什么,然后去计算得到你需要的值。流是按照需求生成的。

    流只能遍历一次,用完之后就不存在了,只能重新创建流才能使用。例如:

		IntStream i = IntStream.of(1,2,3,4);
		i.forEach(System.out::println);<!--forEach输入Consumer-->
		i.forEach(System.out::println);<!--报错,stream has already been operated upon or closed-->
    Collection接口使用的迭代,比如for-each,叫做外部迭代。流则是内部迭代,你只要告诉它干什么就行了。外部迭代你可以看到每一次迭代,而内部迭代你看不到,流帮你做了。

2.流操作

    java.util.stream.Stream有许多操作,但是可以分为两类:一种为中间操作,一种为终端操作。

   中间操作就是操作后返回一个流,比如map,filter,limit等等,中间操作只有在终端操作时才执行。

   终端操作就是把流变为结果不是流的值,比如void,List,Integer等等。比如forEach,count,collect等等。

   使用流一般包含三个动作:生成流,中间操作,终端操作。

3.使用流

   3.1构建流

       由值生成流:
		IntStream i = IntStream.of(1,2,3,4);
		Stream<String> s = Stream.of("a","b","c");
		Stream<String> emptyStream = Stream.empty();<!--创建一个空的流-->
       由数组创建流:
		int[] numbers = {1,2,3,4};
		IntStream intStream = Arrays.stream(numbers);
      由文件生成流:
             java.nio.file.Files很多方法都会返回流。比如Files.lines会返回指定文件各行构成的字符串流
//		hello
//		world
//		stream   >>>data.txt数据
		try(Stream<String> lines = Files.lines(Paths.get("D:\\Desktop\\data.txt"))){
			long words =lines.flatMap(line->Arrays.stream(line.split(""))).distinct().count();
			System.out.println(words);
		}catch(IOException e){
			e.printStackTrace();
		}
      由函数生成流:
             Stream Api有两个静态方法生成流:Stream.iterate,Stream.generate。这两个方法可以生成无限流,可以无限制的计算产生流数据。一定要加limit限制大小。
		Stream.iterate(0, x->x+1).limit(10).forEach(System.out::println);
		Stream.generate(()->2).limit(10).forEach(System.out::println);
      一般使用的是集合生成的流,Collection接口有默认方法产生流。只要实现Collection的类都可以用这个方法。
		List<Integer> list = Arrays.asList(1,2,3,4);
		list.stream().forEach(System.out::println);

   3.2筛选

           流的filter方法,参数为Predicate。返回满足Predicate的元素。也就是返回true的元素。
		List<Integer> list = Arrays.asList(1,2,3,4);
		list.stream().filter(i->i>=2).forEach(System.out::println);
            流的distinct方法返回各异的元素,返回的元素不能重复。
		List<Integer> list = Arrays.asList(1,2,3,4,2,3);
		list.stream().distinct().forEach(System.out::println);
            流的limit方法限制最多返回多少元素。
		List<Integer> list = Arrays.asList(1,2,3,4,2,3);
		list.stream().limit(2).forEach(System.out::println);
           流的skip方法不要前多n个元素,n大于满足条件的元素个数就返回空的流。
		List<Integer> list = Arrays.asList(1,2,3,4,2,3);
		list.stream().filter(i->i>=2).skip(2).forEach(System.out::println);

   3.3映射

        流的map方法作用于每个元素,并且返回一个新的元素,参数为Function。
		List<Integer> list = Arrays.asList(1,2,3,4,2,3);
		list.stream().filter(i->i>=2).map(a->"map"+a).forEach(System.out::println);
       map可以改变Stream的类型,上面就是把Stream<Integer>变为Stream<String>了。
       流的flatMap方法可以把各个数组映射的流合为一个流。例如得到文件字母的个数。
lines.flatMap(line->Arrays.stream(line.split(""))).distinct().count();
       如果直接用map(line->line.spilt(""))得到的是很多个Stream<String[]>。
       如果用map(line->Arrays.stream(line.split("")))得到的是很多个Stream<String>。
       flatMap就是把很多个Stream<String>合为一个Stream<String>这样就可以算字母个数了。不然分为很多个流不能算字母个数。

   3.4查找与匹配

        anyMatch方法参数为Predicate。返回一个boolean值,表示流中是否有元素满足Predicate。
		List<Integer> list = Arrays.asList(1,2,3,4,2,3);
		boolean result = list.stream().anyMatch(i->i==2);
        allMatch方法与anyMatch差不多,表示所有的元素都满足才返回true。 noneMatch方法表示没有元素满足。
        这三个操作都是短路操作。短路操作就是不需要遍历所有的元素就能得到结果。就可&&和||操作符一样。limit方法就是一个短路操作。
         findAny方法,没有参数,表示返回随机的一个元素。返回一个Optional,因为有可能元素不存在。
		List<Integer> list = Arrays.asList(1,2,3,4,2,3);
		Optional<Integer> result = list.stream().findAny();
		System.out.println(result.orElse(0));
        findFirst方法,没有参数,返回第一个元素。返回Optional。

   3.5归约

        流的reduce操作就是将流中的元素结合得到一个值。根据reduce方法中的操作,两两结合得到一个值,然后跟下一个元素结合,就这样一直到最后一个元素,得到最终的值。
		List<Integer> list = Arrays.asList(1,2,3,4,2,3);
		Optional<Integer> sum = list.stream().reduce(Integer::sum);<!--reduce可以指定初始值-->
		Optional<Integer> max = list.stream().reduce(Integer::max);
		Optional<Integer> min = list.stream().reduce(Integer::min);
        流还有max和min方法,参数为Comparator。
		List<Integer> list = Arrays.asList(1,2,3,4,2,3);
		Optional<Integer> max = list.stream().max(comparing(Integer::intValue));
		Optional<Integer> min = list.stream().min(comparing(Integer::intValue));

   3.6数值流

        上面讲的操作如Stream<Integer>会有装箱拆箱的操作。Stream中有IntStreamDoubleStream
LongStream分别表示流中的元素为int,double,long,这样可以避免装箱拆箱。
         mapToIntmapToDoublemapToLong着三个方法可以将Stream<T>转为数值流。数值流中有max,min,sum,average等方法。
		List<A> list = Arrays.asList(new A(1),new A(5),new A(3));
		int sum = list.stream().mapToInt(a->a.getNum()).sum();
		OptionalInt max = list.stream().mapToInt(a->a.getNum()).max();
		OptionalInt min = list.stream().mapToInt(a->a.getNum()).min();
		OptionalDouble ave = list.stream().mapToInt(a->a.getNum()).average();
         boxed() 方法可以将数值流转为对象流。
		List<A> list = Arrays.asList(new A(1),new A(5),new A(3));
		Stream<Integer> i = list.stream().mapToInt(a->a.getNum()).boxed();
         IntStream LongStream 的静态方法,帮助生成这种范围: range rangeClosed 。这两个方法都是第一个参数接受起始值,第二个参数接受结束值。但 range 是不包含结束值的,而 rangeClosed 则包含结束值。
		IntStream.range(1, 100).filter(i->i%2==0).count();



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值