当遇到深层嵌套代码,如for,if,lambda表达式或内部类及这些代码的组合,这时我们可以通过Java 8的语法特性来进行优化。

下面的代码是一个嵌套循环的示例。

public MappedField getMappedField(final String storedName) {
    for (final MappedField mf : persistenceFields) {
        for (final String n : mf.getLoadNames()) {
            if (storedName.equals(n)) {
                return mf;
            }
        }
    }
    return null;
}

重构1:

嵌套的for/if语句通畅可以通过Java 8中的stream来替代。

Optional<String> found = persistenceFields.stream()
.flatMap(mappedField -> mappedField.getLoadNames().stream())
.filter(storedName::equals)
.findFirst();

上述重构代码会返回Optional,但笔者希望返回mappedField对象,再次改造后的代码如下。

persistenceFields.stream()
.filter(mappedField -> {
    for (String name : mappedField.getLoadNames()) {
        if (storedName.equals(name)) {
            return true;
        }
    }
    return false;
}
)
.findFirst()

重构2: 进行更好的封装

重构1还存在一些问题,我们需要了解mappedField的结构,并通过循环遍历其所有name来找到匹配的name。根据迪米特法则(Law of Demeter ),及命令-不要去询问法则(Tell, Don’t Ask), 下面代码应该由MappedField对象来提供对应的方法来判断,而不是由调用者去了解MappedField结构后去写逻辑进行判断。

for (final MappedField mf : persistenceFields) {
    if (mf.hasName(storedName)) {
        return mf;
    }
}

因此将上述代码提取为MappedField类中独立的方法,并命名为hasName。如果使用的IDE 是IDEA则可以通过refractor中的extract功能完成提取。

最后调用hasName方法来替代循环判断逻辑。

接着通过Idea的refractor 中的move功能将代码移动到目标类位置。

接着通过stream来重构hasName方法,hasName方法变更为下面的形式。

public Boolean hasName(String storedName) {
    return getLoadNames().stream()
    .anyMatch(storedName::equals);
}

经过上述步骤最终重构后的代码为。

public MappedField getMappedField(final String storedName) {
    return persistenceFields.stream()
    .filter(mf -> mf.hasName(storedName))
    .findFirst()
    .orElse(null);
}

如需要返回Optional包装的对象则需要去掉orElse。

public Optional<MappedField> getMappedField(final String storedName) {
    return persistenceFields.stream()
    .filter(mf -> mf.hasName(storedName))
    .findFirst();
}

总结

这类代码特征通常为:

  • 存在深层的循环或条件判断嵌套。
  • 需要通过多个getter方法来访问对象内部数据。

重构方法:

考虑tell don’t ask原则,提供专用的方法供外部调用访问数据,而不是通过使用者经过多次访问去获取对象数据。并通过stream提供的操作来完成重构。

————END————

利用Idea重构功能及Java8语法特性——优化深层嵌套代码的更多相关文章

  1. 功能:Java8新特性steam流

    Java8新特性steam流 一.包装数据类型 @Test public void main22() { List<Integer> list = new ArrayList<Int ...

  2. 利用HTML5定位功能,实现在百度地图上定位(转)

    原文:利用HTML5定位功能,实现在百度地图上定位 代码如下: 测试浏览器:ie11定位成功率100%,Safari定位成功率97%,(add by zhj :在手机上测试(用微信内置浏览器打开),无 ...

  3. 基于.net的分布式系统限流组件 C# DataGridView绑定List对象时,利用BindingList来实现增删查改 .net中ThreadPool与Task的认识总结 C# 排序技术研究与对比 基于.net的通用内存缓存模型组件 Scala学习笔记:重要语法特性

    基于.net的分布式系统限流组件   在互联网应用中,流量洪峰是常有的事情.在应对流量洪峰时,通用的处理模式一般有排队.限流,这样可以非常直接有效的保护系统,防止系统被打爆.另外,通过限流技术手段,可 ...

  4. 【Java8新特性】Lambda表达式基础语法,都在这儿了!!

    写在前面 前面积极响应读者的需求,写了两篇Java新特性的文章.有小伙伴留言说:感觉Lambda表达式很强大啊!一行代码就能够搞定那么多功能!我想学习下Lambda表达式的语法,可以吗?我的回答是:没 ...

  5. Java8新特性 1——利用流和Lambda表达式操作集合

    Java8中可以用简洁的代码来操作集合,比如List,Map,他们的实现ArrayList.以此来实现Java8的充分利用CPU的目标. 流和Lambda表达式都是Java8中的新特性.流可以实现对集 ...

  6. Atitit.jdk java8的语法特性详解 attilax 总结

    Atitit.jdk java8的语法特性详解 attilax 总结 1.1. 类型推断这个特别有趣的.鲜为人知的特性1 2. Lambda1 2.1. 内部迭代意味着改由Java类库来进行迭代,而不 ...

  7. Java8 新特性 | 如何风骚走位防止空指针异常

    文章整理翻译自 https://winterbe.com/posts/2015/03/15/avoid-null-checks-in-java/ 文章首发于个人网站: https://www.exce ...

  8. Java8新特性(一)——Lambda表达式与函数式接口

    一.Java8新特性概述 1.Lambda 表达式 2. 函数式接口 3. 方法引用与构造器引用 4. Stream API 5. 接口中的默认方法与静态方法 6. 新时间日期 API 7. 其他新特 ...

  9. java8 新特性精心整理

    前言 越来越多的项目已经使用 Java 8 了,毫无疑问,Java 8 是Java自Java 5(发布于2004年)之后的最重要的版本.这个版本包含语言.编译器.库.工具和 JVM 等方面的十多个新特 ...

随机推荐

  1. PATB 1028. 人口普查(20)

    1028. 人口普查(20) 注意特判合理人数为0,否则格式错误.很暴力的sort排序找出最大最小. 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Stan ...

  2. 常用的方法论-NPS

  3. NEUOJ 1702:撩妹全靠魅力值(CDQ分治三维偏序)

    http://acm.neu.edu.cn/hustoj/problem.php?id=1702 思路:三维偏序模板题,用CDQ分治+树状数组或者树套树.对于三元组(x,y,z),先对x进行排序,然后 ...

  4. redis源码笔记-内存管理zmalloc.c

    redis的内存分配主要就是对malloc和free进行了一层简单的封装.具体的实现在zmalloc.h和zmalloc.c中.本文将对redis的内存管理相关几个比较重要的函数做逐一的介绍 参考: ...

  5. SpringCloud解析之Eureka

    本文基于Spring Cloud Edgware.SR6版本,从功能和架构上解析Eureka,让大家对Eureka有一个较为清晰的认识(本文默认大家对分布式微服务有一个初步的概念和理解,本文不涉及或少 ...

  6. 用Supervisor实现进程守护,在异常退出时自动重启

    程序启动后,有些是以daemon的形式运行,但在意外退出后,如果不能及时重新启动,会有比较严重的影响. 比如Zimg在图片处理中由于某些图片处理失败,会导致zimg进程挂掉,影响正常的服务提供,并且只 ...

  7. 利用jenkins实现自动构建、部署,提升团队开发效率

    一大早就被群里的同学刷银川下雪的消息,看着我都发冷,突觉一阵凉风裹身,是不是该考虑秋裤了. 偏离主题,正文走起...... 使用jenkins目标:利用其结合maven完成自动构建,并部署到tomca ...

  8. Spring Boot + Elasticsearch 实现索引的日常维护

    全文检索的应用越来越广泛,几乎成了互联网应用的标配,商品搜索.日志分析.历史数据归档等等,各种场景都会涉及到大批量的数据,在全文检索方面,方案无外乎Lucene.Solr.Elasticsearch三 ...

  9. 通俗易懂 悲观锁、乐观锁、可重入锁、自旋锁、偏向锁、轻量/重量级锁、读写锁、各种锁及其Java实现!

    网上关于Java中锁的话题可以说资料相当丰富,但相关内容总感觉是一大串术语的罗列,让人云里雾里,读完就忘.本文希望能为Java新人做一篇通俗易懂的整合,旨在消除对各种各样锁的术语的恐惧感,对每种锁的底 ...

  10. 企业如何从“API优先”的策略中获益

    在过去的几年里,全球API经济在以难以置信的速度进行快速地增长.物联网.人工智能.自动驾驶等等众多令人充满期待的技术正蓬勃发展,这也证明了API对于如今整个技术圈子的重要性,也预示着在不久的将来它还将 ...