java –cp ./:_成为Java流专家–第2部分:中级操作

java –cp ./:

就像魔术棒一样,中间操作将一个Stream转换为另一个Stream。 这些操作可以无穷无尽的方式组合在一起,以可读有效的方式执行从简单到高度复杂的任务。

本文是五分之二,其中还有一个GitHub存储库,其中包含每个单元的说明和练习。

  • 第1部分:创建流
  • 第2部分:中级操作
  • 第三部分:终端操作
  • 第4部分:数据库流
  • 第5部分:使用流创建数据库应用程序

中级业务

中间操作充当应如何转换Stream元素的声明性(功能性)描述,它们共同构成了元素流经的管道。 该行结尾的内容自然取决于管道的设计方式。

与机械流水线相反,Stream流水线中的中间操作可能(*)呈现新的Stream,该流可能依赖于先前阶段中的元素。 对于map操作(我们将在稍后介绍),新的Stream甚至可能包含不同类型的元素。

(*)严格来说,不要求执行中间操作来创建新的Stream。 相反,它可以更新其内部状态,或者,如果中间操作未更改任何内容(例如.skip(0) ),则返回上一级的现有Stream。

要了解管道的外观,请回想一下上一篇文章中使用的示例:

 List<String> list = Stream.of( "Monkey" , "Lion" , "Giraffe" , "Lemur" ) 
     .filter(s -> s.startsWith( "L" )) 
     .map(String::toUpperCase) 
     .sorted() 
     .collect(toList());  System.out.println(list); 
 [LEMUR, LION] 

现在,我们将继续详细解释这些操作和其他操作的含义。

根据我们的经验, filter()是Stream API最有用的操作之一。 它使您可以将Stream缩小为适合特定条件的元素。 此类标准必须表示为Predicate (导致boolean值的函数),例如lambda。 以下代码的目的是查找以字母“ L”开头的字符串,并丢弃其他字符串。

 Stream<String> startsWithT = Stream.of( 
    "Monkey" , "Lion" , "Giraffe" , "Lemur"  ) 
     .filter(s -> s.startsWith( "L" )); 
 startsWithT: [Lion, Lemur] 

有一些非常简单但功能强大的操作,提供了一种基于元素在Stream中的位置来选择或丢弃元素的方法。 这些操作中的第一个是limit(n) ,它基本上按照其说的进行操作–它创建一个新流,该流仅包含要应用的流的前n个元素。 下面的示例说明了如何将四个动物的流简化为仅“猴子”和“狮子”。

 Stream<String> firstTwo = Stream.of( 
    "Monkey" , "Lion" , "Giraffe" , "Lemur"  ) 
    .limit( 2 ); 
 firstTwo: [Monkey, Lion] 


类似地,如果我们只对线下的某些元素感兴趣,则可以使用.skip(n) -operation。 如果将skip(2)应用于动物流,则会留下尾巴两个元素“长颈鹿”和“狐猴”。

 Stream<String> firstTwo = Stream.of( 
    "Monkey" , "Lion" , "Giraffe" , "Lemur"  ) 
    .skip( 2 ); 
 lastTwo: [Giraffe, Lemur] 

在某些情况下,流中每个元素只需要出现一次即可。 无需手动筛选出任何重复项,而是为此目的存在了一个指定的操作–distinct distinct() 。 它将使用Object::equals检查是否相等,并返回仅包含唯一元素的新Stream。 这类似于集合。

 Stream<String> uniqueAnimals = Stream.of( 
    "Monkey" , "Lion" , "Giraffe" , "Lemur" , "Lion"  ) 
    .distinct(); 
 uniqueAnimals: [“Monkey”, “Lion”, “Giraffe”, “Lemur”] 


有时元素的顺序很重要,在这种情况下,我们希望控制事物的排序方式。 最简单的方法是使用排序操作,该操作将以自然顺序排列元素。 对于下面的字符串,这表示字母顺序。

 Stream<String> alphabeticOrder = Stream.of( 
     "Monkey" , "Lion" , "Giraffe" , "Lemur"  ) 
    .sorted(); 
 alphabeticOrder: [Giraffe, Lemur, Lion, Monkey] 


有时只能以自然顺序排序可能会有些局限。 幸运的是,可以应用自定义Comparator来检查元素的某些属性。 例如,我们可以按照字符串的长度顺序对它们进行排序:

 Stream<String> lengthOrder = Stream.of( 
     "Monkey" , "Lion" , "Giraffe" , "Lemur"  ) 
    .sorted(Comparator.comparing(String::length)); 
 lengthOrder: [Lion, Lemur, Monkey, Giraffe] 

我们可以应用于Stream的最通用的操作之一是map() 。 通过将Stream的元素映射到另一个值或类型,它可以将其转换为其他元素。 这意味着此操作的结果可以是任何类型R的Stream。 下面的示例执行从StringString的简单映射,将所有大写字母替换为它们的小写字母。

 Stream<String> lowerCase = Stream.of( 
     "Monkey" , "Lion" , "Giraffe" , "Lemur"  ) 
    .map(String::toLowerCase); 
 lowerCase: [monkey, lion, giraffe, lemur] 


映射操作还有三种特殊的实现方式,它们仅限于将元素映射到基本类型intdoubledouble
long

 .mapToInt();  .mapToDouble();  .mapToLong(); 

因此,这些操作的结果始终对应于IntStreamDoubleStreamLongStream 。 下面,我们演示如何使用.mapToInt()将动物映射到其名称的长度:

 IntStream lengths = Stream.of( 
     "Monkey" , "Lion" , "Giraffe" , "Lemur"  ) 
    .mapToInt(String::length); 
 lengths: [ 6 , 4 , 7 , 5 ] 

注意:
String::length等于lambda s -> s.length() 。 我们更喜欢前一种表示法,因为它使代码更简洁易读。


尽管本文功能非常强大,但我们将很难理解它的最后一项操作。 它是有关map()操作,但是,而不是采取一个Function ,其从型变为T到返回类型R它需要一个Function ,其从型变为T并返回一个StreamR 。 然后将这些“内部”流平展为生成的流,从而将内部流的所有元素串联在一起。

 Stream<Character> chars = Stream.of( 
     "Monkey" , "Lion" , "Giraffe" , "Lemur"  ) 
     .flatMap(s -> s.chars().mapToObj(i -> ( char ) i)); 
 chars: [M, o, n, k, e, y, L, i, o, n, G, i, r, a, f, f, e, L, e, m, u, r] 


如果您尚未克隆关联的GitHub存储库,我们建议您现在进行克隆。 本文的内容足以解决名为MyUnit2Intermediate的第二个单元。 相应的Unit2Intermediate接口包含JavaDocs,它们描述MyUnit2MyIntermediate方法的预期实现。

 public interface Unit2Intermediate { 
    /** 
     * Return a Stream that contains words that are 
     * longer than three characters. Shorter words 
     * (ie words of length 0, 1, 2 and 3) 
     * shall be filtered away from the stream. 
     * <p> 
     * A Stream of 
     *     ["The", "quick", "quick", "brown", "fox", 
     *     "jumps", "over", "the", "lazy", "dog"] 
     * would produce a Stream of the elements 
     *     ["quick", "quick", "brown", "jumps", 
     *     "over", "lazy"] 
     */ 
    Stream<String> wordsLongerThanThreeChars(Stream<String> stream); 

提供的测试(例如Unit2MyIntermediateTest )将充当自动分级工具,让您知道您的解决方案是否正确。

下一篇

在下一篇文章中,我们将继续进行终端操作,并探索如何收集,计数或分组管道的结果元素。 在此之前–祝您编程愉快!

s

Per Minborg和Julia Gustafsson

翻译自: https://www.javacodegeeks.com/2019/10/become-a-master-of-java-streams-part-2-intermediate-operations.html

java –cp ./:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值