文/朱季谦

说实话,其实我很讨厌在代码里大量使用if-else,一是因为该类代码属于面向过程的,二嘛,则是会显得代码过于冗余。这篇笔记,主要记录一些自己在工作实践当中针对if-else的优化心得,将会不定期地长期更新。

一、使用策略枚举来优化if-else

看到网上蛮多人推荐使用策略模式来优化if-else,但我总觉得,搞一堆策略类来优化if-else,虽然想法很好,但无意之中很可能又会创造出很多类对象,就显得过于重量了。其实,若想使用策略模式来优化if-else,其实有一种更好的方式,这是策略模式+枚举方式的改良,我以前写过这样一篇优化文章,详细直接点击该文了解:《策略枚举:消除在项目里大批量使用if-else的优雅姿势》

二、使用三目运算符来优化if-else

1、根据if-else条件来判断赋值的,如:

String id="";
if(flag){
id="a";
}else{
id="b";
}

利用三目运算符,可以直接优化成一行代码:

id=flag?"a":"b";

2、利用if-else条件来判断调用方法,如:

Set<String> set1=new HashSet<>();
Set<String> set2=new HashSet<>(); if(flag){
set1.add(id);
}else{
set2.add(id);
}

利用三目运算符,可以直接优化成:

Set<String> set1=new HashSet<>();
Set<String> set2=new HashSet<>();
(flag?set1:set2).add(id);

三、使用Stream优化if中判断条件过多情况

Jdk1.8新特性Stream流有三个这样API,anyMatch,allMatch,noneMatch,各自的作用如下:

  • anyMatch:判断条件里任意一个满足条件,则返回true;
  • allMatch:判断条件里所有都满足条件,则返回true;
  • noneMatch:判断条件里所有都不满足条件,则返回true;

它们的使用方式其实很简单:

List<String> list = Arrays.asList("a", "b", "c","d", "");
//任意一个字符串判断不为空则为true
boolean anyMatch = list.stream().anyMatch( s->StringUtils.isEmpty(s));
//所有字符串判断都不为空则为true
boolean allMatch = list.stream().allMatch( s->StringUtils.isEmpty(s));
//没有一个字符判断为空则为true
boolean noneMatch = list.stream().noneMatch( s->StringUtils.isEmpty(s));

可见,根据以上三种实现方式,可以在某种程度上优化if里判断条件过多的情况,那么,在哪种场景里比较合适利用其优化呢?

在日常实际开发当中,我们可能会看到过这样存在很多判断条件的代码:

 if(StringUtils.isEmpty(str1) || StringUtils.isEmpty(str2) ||
StringUtils.isEmpty(str3) || StringUtils.isEmpty(str4) ||
StringUtils.isEmpty(str5) || StringUtils.isEmpty(str6)
){
.....
}

这时,就可以考虑到,使用stream流来优化,优化后的代码如下:

 if(Stream.of(str1, str2, str3, str4,str5,str6).anyMatch(s->StringUtils.isEmpty(s))){
.....
}

这样优化后,是不是就比那堆if里堆积到一块的条件更为优雅了?

当然,这只是针对或条件的,若是遇到与条件时,同样可以用Stream来优化,例如:

if(StringUtils.isEmpty(str1) && StringUtils.isEmpty(str2) &&
StringUtils.isEmpty(str3) && StringUtils.isEmpty(str4) &&
StringUtils.isEmpty(str5) && StringUtils.isEmpty(str6)
){
.....
}

使用Stream优化后:

if(Stream.of(str1, str2, str3, str4,str5,str6).allMatch(s->StringUtils.isEmpty(s))){
.....
}

四、使用Map优化if-else

优化量比较多的面向过程的if-else语句,还可以考虑使用Map来优化,虽然在一定程度上,创建一个额外map会占用内存,但那丁点内存对于现阶段计算机而言,可以说不足挂齿。
下面使用一个案例来介绍下————

在一些祖传老代码当中,可能遇到过类似这样又臭又冗余的if-else写法:

public String getDay(String day){
if("Monday".equals(day)){
return "今天上英语课";
}else if("Tuesday".equals(day)){
return "今天上语文课";
}else if("Wednesday".equals(day)){
return "今天上数学课";
}else if("Thursday".equals(day)){
return "今天上音乐课";
}else if("Sunday".equals(day)){
return "今天上编程课";
}else{
......
}
}

这时,可以根据具体场景,来考虑是否可以利用Map优化,使用Map优化的方式,是先在该类中定义一个static的map,类似这样:

public static final  Map<String,String> dayMap=  ImmutableMap.<String, String>builder()
.put("Monday","今天上英语课")
.put("Tuesday","今天上语文课")
.put("Wednesday","今天上数学课")
.put("Thursday","今天上音乐课")
.put("Sunday","今天上编程课")
.build();

定义完后,就直接在先前使用if-else的方法里,进行这样优化:

public String getDay(String day){
return dayMap.get(day);
}

这样优化后,业务方法里的判断获取值的处理,是不是就清爽了很多,当然,这只是针对量比较多的if-else而言,若是比较少的判断语句,再额外定义一个map来搞,隐约有画蛇添足的嫌疑。

细心的读者可能会发现, 我在定义map的时候,使用到了一个ImmutableMap的东西,这是Google Guava里的一个类,可生成一个不可变的Map对象,这就意味着,初始化定义后,后续就无法再put修改了,它的这个特性可以保证线程的安全。一般用来替换if-else的map,我们就是要求在初始化定义后,就不会再允许修改了,因此,这个ImmutableMap生成的map,可以很好地帮我们实现这一点。另外,最重要一点是,使用这个ImmutableMap,可以实现链式编程,就像上面定义的链式写法,若是用传统的map定义,就每次都要map.put()、map.put()地赋值。

关于ImmutableMap的使用与原理,后续我会专门写一篇文章来介绍。

五、使用枚举优化if-else

前面提到过可使用策略枚举来优化大批量的if-else,当然,同样可以考虑直接使用枚举来优化,其效果与map的处理效果类似。

同样,还是用前面判断课程的if-else为案例来优化。

首先,先在类中定义一个枚举:

public enum dayEnum {
Monday("今天上英语课"),
Tuesday("今天上语文课"),
Wednesday("今天上数学课"),
Thursday("今天上音乐课"),
Sunday("今天上编程课"); public String value; dayEnum(String value){
this.value=value;
}
}

定义完后,就可以类似前面map的方式,直接将判断值去枚举里获取,然后直接返回获取到的值,这样写法是不是也比较优雅了。

public String getDay(String day){
return dayEnum.valueOf(day).value;
}

六、使用Optional类优化if-else

在实际工作中,我曾经遇到类似这样的代码,看起来像没什么问题,但如果其中某个属性值不幸为null,那么,恭喜你,你将会喜提一个NullPointerException异常。

String name=school.getGrades().getStuendt().getName();

若要处理这个可能出现的空指针异常,传统写法,可以写一堆if-else语句来处理,就像这样子——

String name=null;
if(school!=null){
Grades grade=school.getGrades();
if(grade!=null){
Student student=grade.getStuendt();
if(student!=null){
name = student.getName();
}
}
}

作为一个极度讨厌if-else的人士,怎么能容忍这一堆层层嵌套的代码存在呢!

在遇到这种层层嵌套的if-else判断时,可以考虑使用jdk1.8新特性Optional 类来优化,优化后的效果如下,顿时又优雅了很多。

String name = Optional.ofNullable(school)
.flatMap(School::getGrades)
.flatMap(Grades::getStuendt)
.map(Student::getName)
.orElse(null);

本文属于编程技巧总结,后续将持续更新......

Java编程技巧:if-else优化实践总结归纳的更多相关文章

  1. 偏执却管用的10条Java编程技巧

    本文由 ImportNew - LynnShaw 翻译自 javacodegeeks.欢迎加入翻译小组.转载请见文末要求. 经过一段时间的编码(咦,我已经经历了将近20年的编程生涯,快乐的日子总是过得 ...

  2. 30 个java编程技巧(最佳实践的初学者)

    1.return 一个空的集合,而不是 null 如果一个程序返回一个没有任何值的集合,请确保一个空集合返回,而不是空元素.这样你就不用去写一大堆 ”if else” 判断null元素. Java 的 ...

  3. 30 个java编程技巧

    1.return 一个空的集合,而不是 null 如果一个程序返回一个没有任何值的集合,请确保一个空集合返回,而不是空元素.这样你就不用去写一大堆 ”if else” 判断null元素. Java 的 ...

  4. Java基础学习总结(59)——30 个java编程技巧

    1.return 一个空的集合,而不是 null 如果一个程序返回一个没有任何值的集合,请确保一个空集合返回,而不是空元素.这样你就不用去写一大堆 "if else" 判断null ...

  5. 性能调优 -- Java编程中的性能优化

    String作为我们使用最频繁的一种对象类型,其性能问题是最容易被忽略的.作为Java中重要的数据类型,是内存中占据空间比较大的一个对象.如何高效地使用字符串,可以帮助我们提升系统的整体性能. 现在, ...

  6. Java 编程技巧之数据结构

    前言: 介绍几种常见的java数据结构及应用. 使用HashSet判断主键是否存在 HashSet 实现 Set 接口,由哈希表(实际上是 HashMap )实现,但不保证 set  的迭代顺序,并允 ...

  7. java 编程技巧

    1. 参数可空: @注解表示修改的字段可为空值.看它的定义,可以修饰在方法,参数和字段(类似c#中的?)上. @Target({ElementType.METHOD, ElementType.PARA ...

  8. java编程技巧

    欢迎提出建议指出错误互相交流. 1.统计对象数量,比如统计一共发射了多少颗子弹. public class Bullet { public static int count = 0; public B ...

  9. java编程技巧和心得

    1.在一个类中修改或调用另一个类的变量: 只需要将该变量用public static 这个修饰符修饰,再用类名直接调用即可 2.实现对只有下标不同变量的操作 解决思路:可以将这些变量放在一个数组里,在 ...

随机推荐

  1. 批处理用WINRAR只压缩某类型的文件

    1:新建文件夹sql back 和 back,在sql back 文件夹内新建test1.dbb和test2.bak文件 2:新建批处理文件rar.bat,编辑文件: @echo off for %% ...

  2. Markdown编辑器怎么用

    Markdown编辑器怎么用 1.代码块 快速创建一个代码块 // 语法: // ```+语言名称,如```java,```c++ 2.标题 语法:#+空格+标题名字,一个#表示一级标题,两个#表示二 ...

  3. 细数 C++ 那些比起 C语言 更爽的特性

    结构体定义 C: typedef struct Vertex { int x, y, z; } Vertex; Vertex v1 = { 0 }; // or struct Vertex { int ...

  4. .Net Core·寄托于IIS的REST服务405的问题

    阅文时长 | 0.48分钟 字数统计 | 828.8字符 主要内容 | 1.引言&背景 2.声明与参考资料 『.Net Core·寄托于IIS的REST服务405的问题』 编写人 | SCsc ...

  5. bashshell删除列

    删除所有空白列cat yum.log | awk '{$1=$2=$3=$4=null;print $0}'>>yum.log7删除文件中的所有空格sed -i s/[[:space:]] ...

  6. 性能工具 stream 最新版本5.10 The STREAM benchmark

    官网下载最新性能工具 stream 最新版本5.10 https://github.com/jeffhammond/STREAM 官网下载最新性能工具 stream 最新版本5.10   http:/ ...

  7. 在Windows上使用 Python 安装+ win10启用长路径

    https://docs.python.org/zh-cn/3/using/windows.html 成功20200131 https://docs.python.org/zh-cn/3/using/ ...

  8. 大数据 什么是 ETL

    ETL 概念 ETL 这个术语来源于数据仓库,ETL 指的是将业务系统的数据经过抽取.清洗转换之后加载到数据仓库的过程.ETL 的目的是将企业中的分散.零乱.标准不统一的数据整合到一起,为企业的决策提 ...

  9. 【长期更新】Ubuntu常用命令备忘录

    Error  Could not get lock /var/lib/dpkg/lock 出现这个问题可能是有另外一个程序正在运行,导致资源被锁不可用.而导致资源被锁的原因可能是上次运行安装或更新时没 ...

  10. linux环境下时区无法设置(UTC无法更改为CST)的问题解决

    在进行linux下修改时区的时候 总是修改不了 修改成 Asia/Shanghai  但是 时区总是 +0000 却不是想要的+0800 按照网上的方法 A方法:tzselect:执行tzselect ...