java8-流的操作

流的操作

流的使用一般包括三件事:

一个数据源来执行一个查询;

一个中间操作链,形成一条流的流水线;

一个终端操作,执行流水线,并能生成结果

中间操作

操作类型返回类型操作参数函数描述符
filter中间StreamPredicateT -> boolean
map中间StreamFunction<T,R>T->R
limit中间Stream
sorted中间StreamComparator(T,T)->int
distinct中间Stream

终端操作

操作类型目的
forEach终端消费流中的每个元素并对其应用Lambda.这一操作返回void
count终端返回流中元素的个数,这一操作返回long
collect终端把流归约成一个集合,比如List,Map甚至是Integer

使用流

筛选

出了filter ,流还支持一个叫做distinct的方法,它会返回一个元素各异(根据流所生成元素的hashCode和equals方法实现)的流.例如,如下代码会筛选出列表中所有的偶数,并确保没有重复

 
  1. List<Integer> numbers = Arrays.asList(1,2,1,3,3,2,4);

  2. numbers.stream()

  3. .filter(i -> i%2 ==0)

  4. .distinct()

  5. .forEach(System.out::println);

截断流

流支持limit(n) 方法,该方法会返回一个不超过给定长度的流.

 
  1. List<Dish> dishes = menu.stream()

  2. .filter(d->d.getCalories()>300)

  3. .limit(3)

  4. .collect(toList());

跳过元素

流还支持skip(n)方法,返回一个扔掉了前n个元素的流.

List<Dish> dishes = menu.stream().filter(d->d.getCalories()>300).skip(2).collect(toList());

映射

对流中每一个元素应用函数

例如: 如果要找出每道菜的名称有多长,则如下:

List<Integer> dishNameLengths = menu.stream().map(Dish::getname).map(String::length).collect(toList())

流的扁平化

例如:给定单词列表["hello","world"],你想要返回列表["h","e","l","l","o","w","o","r","l","d"]

利用上面的可能是:

words.stream().map(word->word.split("")).distinct().collect(toList());

这个方法的问题自傲与,传递给map方法的Lambda为每个单词返回一个String[] (String列表),因此,map返回的流实际上是Stream< String[] >类型的.你真正想要的是用Stream< String > 来表示一个字符流

1.尝试使用map和Arrays.stream()

 
  1. String[] arrayOfWords = {"GoodBye","World"};

  2. Stream< String> streamOfWords = Arrays.stream(arrayOfWords);

2.使用flatMap

 
  1. String[] arrayOfWords = {"GoodBye","World"};

  2. Stream< String> streamOfWords = Arrays.stream(arrayOfWords);

  3. List<String[]> collect = streamOfWords.map(m -> m.split("")).collect(toList());

  4. System.out.println(collect);

例2:

给定列表[1,2,3] 和[3,4] ,返回[(1,3),(1,4),(2,3).....]

 
  1. List<Integer> integers = Arrays.asList(1, 2, 3);

  2. List<Integer> integers1 = Arrays.asList(3, 4);

  3. List<int[]> collect = integers.stream()

  4. .flatMap(i -> integers1.stream()

  5. .map(j -> new int[]{i, j}))

  6. .collect(toList());

  7. collect.forEach(i -> {

  8. String s = Arrays.toString(i);

  9. System.out.println(s);

  10. });

例3:

扩展前面的例子,只返回综合能被3正处的数对呢?

 
  1. List<Integer> int1 = Arrays.asList(1, 2, 3);

  2. List<Integer> int2 = Arrays.asList(3, 4);

  3. List<int[]> collect = int1.stream().flatMap(i -> int2.stream().filter(j -> (i + j) % 3 == 0).map(j -> new int[]{i, j})).collect(toList());

  4. System.out.println(collect);

查找和匹配

匹配

1.检查谓词是否至少匹配一个一元素

anyMatch方法可以回答"流中是否有一个元素能匹配给定的谓词"

 
  1. if(menu.stream().anyMatch(Dish::isVegetarian)){

  2. System.out.println("The menu is vegetarian friendly!!");

  3. }

2.检查谓词是否匹配所有元素

例如:用allMatch来看看菜品是否有利健康

boolean isHealthy = menu.stream().allMatch(d->d.getCalories()<1000);

3.确保流中没有任何元素与给定的谓词匹配 noneMatch

boolean isHealthy = menu.stream().noneMatch(d->d.getCalories()<1000);

查找

findAny方法将返回当前流中的任意元素

Optional<Dish> dish = menu.stream().filter(Dish::isVegetarian).findAny();

查找第一个元素

 
  1. List<Integer> someNumbers = Arrays.asList(1,2,3,4,5);

  2. Optional<Integer> firstSquareDivisibleByThree =

  3. someNumbers.stream()

  4. .map(x->x*x)

  5. .filter(x->x%3 == 0)

  6. .findFirst();

归约

元素求和 reduce

reduce接受两个参数

一个初始值,这里是0

一个BinaryOperator< T >来将两个元素结合起来产生一个新值 ,这里我们用的是lambda(a,b)->a+b;

int sum = numbers.stream().reduce(0,(a,b)->a+b);

相乘:

int product = numbers.stream().reduce(1,(a,b)->a*b);

在java 8 中,Integer类现有了一个静态的sum方法来对两个数求和

int num=numbers.stream().reduce(0,Integer::sum);

最大值:

Optional<Integer> max = numbers.stream().reduce(Intger::max)

最小值:

Optional<Integer> min = numbers.stream().reduce(Integer::min);

数值流

原始类型流特化

java 8 引入了三个原始类型特化流接口来专门支持处理数值流的方法:IntStream . DoubleStream 和LongStream,.

分别将流中的元素特化成为int,long ,double,从而避免了暗含装箱成本

1.映射到数值流

将流转化为特化版本的常用方法是mapToInt,mapToDouble ,mapToLong.

 
  1. int calaories = menu.stream()

  2. .mapToInt(Dish::getCalories)//返回一个IntStream

  3. .sum();

2.转换回対向流 boxed

 
  1. IntStream intStream = menu.stream().mapToInt(Dish::getCalories);

  2. Stream<Integer> stream = intStream.boxed();

3.默认值OptionalInt

IntStream中有个默认值0,所以,为了解决求最大值或最小值的问题 ,使用Optional原始类型特化版本:OptionalInt,

OptionalDouble,OptionalLong.

例如:要找到IntStream中的最大元素,可以调用max方法,它会返回一个OptionalInt:

 
  1. OptionalInt maxCalories = menu.stream()

  2. .mapToInt(Dish::getCalories)

  3. .max();

  4. //如果没有最大值的话,可默认一个最大值

  5. int max = maxCalories.orElse(1);

4.数值范围

假如你想要生成1到100之间的所有数字. java8引入了两个可以用于IntStream和LongStream的静态方法,帮助生成这种范围:range和rangeClosed. 这两个方法都是第一个参数接受起始值,第二个参数接受结束值.但是range是不包含结束值的,而rangeClosed则包含结束值

 
  1. IntStream evenNumbers = IntStream.rangeClosed(1,100)

  2. .filter(n -> n % 2 == 0);//一个从1到100的偶数流

  3. System.out.println(evenNumbers.count());//从1到100有50个偶数

构建流

由值创建流

可以使用静态方法Stream.of,通过显示值创建一个流.它可以接受任意数量的参数

 
  1. Strean<String> stream = Stream.of("java 8","Lambdas ","In ","Action");

  2. stream.map(String::toUpperCase).forEach(System.out::println);

  3. //使用empty得到一个空流

  4. Stream<String> emptySteam = Stream.empty();

由数组创建流

 
  1. int[] numbers = {2,3,4,11,13};

  2. int sum = Arrays.stream(numbers).sum();

由文件生成流

 
  1. long uniqueWords = 0;

  2. try(Stream<String> lines =

  3. Files.lines(Paths.get("data.txt"),Charset.defaultCharset())){

  4. uniqueWords = lines.flatMap(line -> Arrays.stream(line.split(" ")))

  5. .distinct()

  6. .count();

  7. }catch(IOException e){

  8. }

由函数生成流:创建无限流

Stream.iterate和Stream.generate ,一般来说应该使用limit(n)来对这种流加以限制,以避免打印无穷多个值

1.迭代

 
  1. Stream.iterate(0,n -> n+2)

  2. .limit(10)

  3. .forEach(System.out::println);

2.生成

与iterate方法类似,generate方法也可生成一个无限流.但generate不是依次对每个新生成的值应用函数的.它接受一个Supplier< T >类型的Lambda提供新的值

 
  1. Stream.generate(Math::random)

  2. .limit(5)

  3. .forEach(System.out::println);

 
  1. //下面的代码就是出安静了一个斐波那契

  2. IntSupplier fib = new IntSuppleir(){

  3. private int previous = 0;

  4. private int current = 1;

  5. public int getAsint(){

  6. int oldPrevious = this.previous;

  7. int nextValue = this.previous + this.current;

  8. this.previous = this.current;

  9. this.current = nextValue;

  10. return oldPrevious;

  11. }

  12. };

  13. IntStream.generate(fib).limit(10).forEach(System.out::println);

转载于:https://www.cnblogs.com/luozhiyun/p/7988521.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值