java8实战之三流的使用

流的使用

总结
  1. Streams API可以表达复杂的数据处理查询。
  2. 可以使用filter、distinct、skip和limit对流做筛选和切ྞ。
  3. 可以使用map和flatMap提取或转换流中的元素。
  4. 可以使用findFirst和 findAny方法查找流中的元素。你可以用allMatch、
    noneMatch和anyMatch方法让流匹配给定的谓词。
  5. 这些方法都利用了短路:找到结果就立即停止计算;没有必要处理整个流。
  6. 可以利用reduce方法将流中所有的元素迭代合并成一个结果,例如求和或查找最大元素。
  7. filter和map等操作是无状态的,它们并不存储任何状态。reduce等操作要存储状态才能计算出一个值。sorted和distinct等操作也要存储状态,因为它们需要把流中的所有元素缓存起来才能返回一个新的流。这种操作称为有状态操作。
  8. 流有三种基本的原始类型特化:IntStream、DoubleStream和LongStream。它们的操作也有相应的特化。
  9. 流不仅可以从集合创建,也可从值、数组、文件以及iterate与generate等特定方法创建。
筛选和切片
1、谓词

该操作会接受一个៊词(一个返回boolean的函数)作为参数,并返回一个包括所有符合谓词的元素的流。例如,筛选出所有素菜,创建一张素食菜单:

List<Dish> vegetarianMenu = menu.stream()
            .filter(Dish::isVegetarian)
            .collect(toList());
2、去重

以下代码会筛选出列表中所有的偶数,并确保没有重复

List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
    numbers.stream()
            .filter(i -> i % 2 == 0)
            .distinct()
            .forEach(System.out::println);
3、限定

选出热量超过300卡路里里的头三道菜:

    List<Dish> dishes = menu.stream()
            .filter(d -> d.getCalories() > 300)
            .limit(3)
            .collect(toList());
4、忽略

下面的代码将跳过超过300卡路里里的头两道菜,并返回剩下的

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

一个非常常见的数据处理套路就是从某些对象中选择信息。比如在SQL里,你可以从表中选择一列。Stream API也通过map和flatMap方法提供了类似的工具。

    List<String> dishNames = menu.stream()
            .map(Dish::getName)
            .collect(toList());

使用flatMap方法的效果是,各个数组并不是分别映射成一个流,而是映射成流的内容。所有使用map(Arrays::stream)时生成的单个流都被合并起来,即扁平化为一个流。

List<String> uniqueCharacters =
			 words.stream()
			 .map(w -> w.split(""))
			 .flatMap(Arrays::stream)
			 .distinct()
			 .collect(Collectors.toList()); 
查找和匹配
1、anyMatch、allMatch、noneMatch

流中是否有一个元素能匹配给定的谓词

if(menu.stream().anyMatch(Dish::isVegetarian)){
 System.out.println("The menu is (somewhat) vegetarian friendly!!");
} 

看流中的元素是否都能匹配给定的谓词

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

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

boolean isHealthy = menu.stream()
 .noneMatch(d -> d.getCalories() >= 1000); 
2、findAny、findFirst

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

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

有序的流查找第一个元素

List<Integer> someNumbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> firstSquareDivisibleByThree =
		 someNumbers.stream()
		 .map(x -> x * x)
		 .filter(x -> x % 3 == 0)
		 .findFirst();
归约
1、求和

reduce接受两个参数:
一个原始值,这里是0;
一个BinaryOperator来将两个元素结合起来产生一个新值;

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

映射到数值流
IntStream、DoubleStream和LongStream对应mapToInt、mapToDouble和mapToLong避免装箱操作

int calories = menu.stream().mapToInt(Dish::getCalories).sum(); 

转换回对象流

IntStream intStream = menu.stream().mapToInt(Dish::getCalories);
Stream<Integer> stream = intStream.boxed(); 
2、最值
Optional<Integer> max = numbers.stream().reduce(Integer::max); 
Optional<Integer> min = numbers.stream().reduce(Integer::min); 
3、范围(range和rangeClosed)

这两个方法都是第一个参数接受起始值,第二个参数接受结束值。但
range是不包含结束值的,而rangeClosed则包含结束值。

IntStream evenNumbers = IntStream.rangeClosed(1, 100)
			 .filter(n -> n % 2 == 0);
System.out.println(evenNumbers.count());
构建流
1、值创建流
Stream<String> stream = Stream.of("Java 8 ", "Lambdas ", "In ", "Action"); 
2、数组创建流
int sum = Arrays.stream(numbers).sum(); 
3、文件生成流
long uniqueWords = 0;
try(Stream<String> lines =
 Files.lines(Paths.get("data.txt"), Charset.defaultCharset())){
uniqueWords = lines.flatMap(line -> Arrays.stream(line.split(" ")))
 .distinct()
 .count();
}
catch(IOException e){

} 
4、函数生成流
Stream.iterate(0, n -> n + 2)
 .limit(10)
 .forEach(System.out::println); 
Stream.generate(Math::random)
 .limit(5)
 .forEach(System.out::println); 

以上就是对流的基本使用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值