美文网首页
写给大忙人的javaSE8(3)-流操作使用总结

写给大忙人的javaSE8(3)-流操作使用总结

作者: 青山有扶苏 | 来源:发表于2019-03-03 22:31 被阅读0次
学而不思则罔,思而不学则殆。

温馨提示:这一接基本上是前面一节中的一些总结和使用注意事项,可以酌情跳过。

前面一节中,说明了常用的Stream操作的部分常用API,本节中,将这些api用一个例子整合起来使用。
1.api整合操作
先假设提出一个需求:
例如,我们现在有6个魔法师,他们来自不同的种族,不同的地区,不同的性别,甚至擅长各种各样的技能魔法。
任务:在魔法师队伍中找到人类魔法师,并计算出他们来自哪些地区。

按照以往的方式,在for循环中,根据race获取到魔法师是否为人类“homan”,并且并且将这些魔法师的来源地whence输出到一个Set,使用Set是因为,有可能两个或以上的魔法师来自同一个地区,但是我们这里的需求是,同一个地区不能出现两次。

Set<String> sets = new HashSet<>();
for(int i = 0; i < magicians.size();i++) {
  if ("human".equals(magicians.get(i).getRace())) {
    sets.add(magicians.get(i).getWhence())
  } 
}

可以这么理解。
1.过滤出魔法师种族为人类的数据
2.找到魔法师的来源地
3.将魔法师来源放入 sets集合。

接下来。我们将上面这段for循环改成 Stream方式,来练习一下使用Stream的API是如何完成上面这个任务的。

//找出魔法师中 属于人类的魔法师
Set<String> whences = magicians.stream()
        .filter(mg -> mg.getRace().equals("homan"))
        .map(mg -> mg.getWhence())
        .collect(Collectors.toSet());

实际上,Stream操作更能直观的表达出我们的意图,首先,filter找出race为人类“homan”的魔法师,使用map操作获取魔法师的来源地 whence,然后将这个Stream使用提早取值的方法 collect转换成一个 Set。现在,是不是觉得Stream或许可以在你的代码中替代哪些复杂的操作了?

2.重构以往的旧代码。

以往复杂的代码,在采用流的方式重构,重构过程中,每一步都能确保通过单元测试,以保证代码能够正常工作。

刚接触Stream时,可以先从for循环入手,
1.首先使用Stream的forEach方法替代掉旧代码中的for循环。
2.使用filter方式进行一些逻辑判定。
3.使用map,flatmap等方式替换一些业务逻辑
4.使用及早求值方法得到最终结果。

3.多次调用流的操作。

在前面的诸多例子中,我们大多时候都是用链式的方法调用Stream的api进行求值。但是你也可以每一步都强制采用及早求值法,不过不建议这么做。
例如我们找魔法师的例子中

//使用链式方法
Set<String> whences = magicians.stream()
        .filter(mg -> mg.getRace().equals("homan"))
        .map(mg -> mg.getWhence())
        .collect(Collectors.toSet());

//每一步强制对函数求值,而不是将所有方法调用连接一起
//1.先过滤出种族为人类的魔法师
List<Magician> magicianList = magicians.stream()
        .filter(mg -> mg.getRace()
        .equals("homan")).collect(Collectors.toList());

//2.将魔法师的来源地放入map
Set<String> whencesSet = magicianList.stream()
        .map(mg -> mg.getWhence()).collect(Collectors.toSet());

毫无疑问,这种方也是可以达到目的的,不过该方法有以下几点区别。
1.代码可读性差,样板代码过多,隐藏了真正的业务逻辑。
2.效率差,每一步都要对流及早求值,生成新的集合。
3.代码充斥着一堆垃圾变量,他们只是用来保存中间结果,除此之外,毫无用处。
4.难于自动并行化处理。

不过,刚开始接触流的方式时,可能会不知不觉中写出类似的代码,若有发现时应及时纠正,避免习惯的养成。

4.正确使用Lambda表达式。
使用lambda表达式时,要尽量避免产生副作用,这一点非常重要。没有副作用的函数不会改变程序或外接状态。在lambda表达式中向控制台输出信息或者给变量{不是lambda表达式内部的变量}赋值也是一种副作用,而且更难察觉, 无论何时,将lambda表达式传给Stream上的高阶函数,都应该尽量避免副作用。唯一例外的事forEach方法,因为它是一个终结方法。

保持最好的心态,来迎接趣味人生

相关文章

  • 写给大忙人的javaSE8(3)-流操作使用总结

    温馨提示:这一接基本上是前面一节中的一些总结和使用注意事项,可以酌情跳过。 前面一节中,说明了常用的Stream操...

  • 写给大忙人的javaSE8(2)-常用流操作

    java8中的 StreamAPI 非常丰富,本文介绍几种比较重要的API。 collect(toList()) ...

  • Java面试相关书籍

    Java SE 写给大忙人看的Java核心技术:Core Java压缩版 写给大忙人看的Java SE 8:Jav...

  • Java I/O流(二)

    继续讲解字符流操作方式 3.使用字符流来操作文件 使用字节流来操作汉字或者特殊符号的时候容易乱码,建以使用字符流现...

  • JavaSE8流库

    一、流库介绍 1.1 流提供了一种让我们可以在比集合更高的概念级别上指定计算的数据视图。通过流,我们可以说明想要完...

  • 并发知识6

    对并发散列映射的批操作 javase8 为散列映射提供批操作,即使有其他线程在处理映射,这些操作也能安全的执行。批...

  • Java8 的一些新特性

    最近看了《写给大忙人看的java se 8》这本书,简单的记录一下读后感和总结。由于本人不做Java GUI 方面...

  • Java I/O操作

    主要就是对各种输入输出流使用的总结 字节流使用情况:对流中的数据以字节为单位进行读取写入操作,不关心内容 字符流使...

  • IO流

    1.IO流总结 (1)按操作方式分类结构图:image.png (2)按操作对象分类结构图image.png (3...

  • SpringBoot2.0响应式编程系列(三)-Stream流

    1 Stream流编程-概念 2 流的创建 3 流的中间操作 中间操作会返回一个新的流,并且操作是延迟执行的,它不...

网友评论

      本文标题:写给大忙人的javaSE8(3)-流操作使用总结

      本文链接:https://www.haomeiwen.com/subject/zgimuqtx.html