Java8 优雅简化代码

您所在的位置:网站首页 orelsenull Java8 优雅简化代码

Java8 优雅简化代码

2023-03-06 17:35| 来源: 网络整理| 查看: 265

1. 使用 Stream 简化集合操作

见Java8 Stream流操作总结

2. 使用 Optional 简化判空逻辑

空指针异常(NullPointerExceptions)是 Java 最常见的异常之一,一直以来都困扰着 Java 程序员。一方面,程序员不得不在代码中写很多null的检查逻辑,让代码看起来非常臃肿;另一方面,由于其属于运行时异常,是非常难以预判的。

为了预防空指针异常,Google的Guava项目率先引入了Optional类,通过使用检查空值的方式来防止代码污染,受到Guava项目的启发,随后在Java 8中也引入了Optional类。

Optional 类位于java.util包下,是一个可以为 null 的容器对象,如果值存在则isPresent()方法会返回 true ,调用 get() 方法会返回该对象,可以有效避免空指针异常。

2.1 创建Optional对象

empty()、of()、ofNullable()

//可以使用静态方法 empty() 创建一个空的 Optional 对象 Optional empty = Optional.empty(); System.out.println(empty); // 输出:Optional.empty //可以使用静态方法 of() 创建一个非空的 Optional 对象 Optional opt = Optional.of("沉默王二"); System.out.println(opt); // 输出:Optional[沉默王二] //当然了,传递给 of() 方法的参数必须是非空的,也就是说不能为 null,否则仍然会抛出 NullPointerException。 String name = null; Optional optnull = Optional.of(name); //可以使用静态方法 ofNullable() 创建一个即可空又可非空的 Optional 对象 String name = null; Optional optOrNull = Optional.ofNullable(name); System.out.println(optOrNull); // 输出:Optional.empty 2.2 判断值是否存在

isPresent(); isEmpty()

//可以通过方法 isPresent() 判断一个 Optional 对象是否存在,如果存在,该方法返回 true,否则返回 false——取代了 obj != null 的判断。 Optional opt = Optional.of("沉默王二"); System.out.println(opt.isPresent()); // 输出:true Optional optOrNull = Optional.ofNullable(null); System.out.println(opt.isPresent()); // 输出:false //Java 11 后还可以通过方法 isEmpty() 判断与 isPresent() 相反的结果。 Optional opt = Optional.of("沉默王二"); System.out.println(opt.isPresent()); // 输出:false Optional optOrNull = Optional.ofNullable(null); System.out.println(opt.isPresent()); // 输出:true 2.3 非空表达式

ifPresent(),允许我们使用函数式编程的方式执行一些代码,因此,我把它称为非空表达式。如果没有该方法的话,我们通常需要先通过 isPresent() 方法对 Optional 对象进行判空后再执行相应的代码:

Optional optOrNull = Optional.ofNullable(null); if (optOrNull.isPresent()) { System.out.println(optOrNull.get().length()); }

有了 ifPresent() 之后,情况就完全不同了,可以直接将 Lambda 表达式传递给该方法,代码更加简洁,更加直观。

Optional opt = Optional.of("沉默王二"); opt.ifPresent(str -> System.out.println(str.length())); //Java 9 后还可以通过方法 ifPresentOrElse(action, emptyAction) 执行两种结果,非空时执行 action,空时执行 emptyAction。 Optional opt = Optional.of("沉默王二"); opt.ifPresentOrElse(str -> System.out.println(str.length()), () -> System.out.println("为空")); 2.4 设置(获取)默认值

有时候,我们在创建(获取) Optional 对象的时候,需要一个默认值,orElse() 和 orElseGet() 方法就派上用场了。

orElse() 方法用于返回包裹在 Optional 对象中的值,如果该值不为 null,则返回;否则返回默认值。该方法的参数类型和值得类型一致。

String nullName = null; String name = Optional.ofNullable(nullName).orElse("沉默王二"); System.out.println(name); // 输出:沉默王二

orElseGet() 方法与 orElse() 方法类似,但参数类型不同。如果 Optional 对象中的值为 null,则执行参数中的函数。

String nullName = null; String name = Optional.ofNullable(nullName).orElseGet(()->"沉默王二"); System.out.println(name); // 输出:沉默王二

orElseGet性能更好一点,因为无论Optional 对象中的值是不是为空,orElse都会执行,只是不返回而已。但是通常这里的逻辑不会很复杂,所以影响不大。

2.5 获取值

直观从语义上来看,get() 方法才是最正宗的获取 Optional 对象值的方法,但很遗憾,该方法是有缺陷的,因为假如 Optional 对象的值为 null,该方法会抛出 NoSuchElementException 异常。这完全与我们使用 Optional 类的初衷相悖。

public class GetOptionalDemo { public static void main(String[] args) { String name = null; Optional optOrNull = Optional.ofNullable(name); System.out.println(optOrNull.get()); } }

建议 orElseGet() 方法获取 Optional 对象的值。

2.6 filter 、map

filter() 方法的参数类型为 Predicate(Java 8 新增的一个函数式接口),也就是说可以将一个 Lambda 表达式传递给该方法作为条件,如果表达式的结果为 false,则返回一个 EMPTY 的 Optional 对象,否则返回过滤后的 Optional 对象。

map() 方法,该方法可以按照一定的规则将原有 Optional 对象转换为一个新的 Optional 对象,原有的 Optional 对象不会更改。

public class OptionalMapFilterDemo { public static void main(String[] args) { String password = "password"; Optional opt = Optional.ofNullable(password); Predicate len6 = pwd -> pwd.length() > 6; Predicate len10 = pwd -> pwd.length() < 10; Predicate eq = pwd -> pwd.equals("password"); boolean result = opt.map(String::toLowerCase).filter(len6.and(len10 ).and(eq)).isPresent(); System.out.println(result); } }

总结:使用 Optional,不仅可以避免使用 Stream 进行级联调用的空指针问题;更重要的是,它提供了一些实用的方法帮我们避免判空逻辑。

如下是一些例子,演示了如何使用 Optional 来避免空指针,以及如何使用它的 fluent API 简化冗长的 if-else 判空逻辑:

@Test(expected = IllegalArgumentException.class) public void optional() { //通过get方法获取Optional中的实际值,很少用到 assertThat(Optional.of(1).get(), is(1)); //通过ofNullable来初始化一个null,通过orElse方法实现Optional中无数据的时候返回一个默认值 assertThat(Optional.ofNullable(null).orElse("A"), is("A")); //OptionalDouble是基本类型double的Optional对象,isPresent判断有无数据 assertFalse(OptionalDouble.empty().isPresent()); //通过map方法可以对Optional对象进行级联转换,不会出现空指针,转换后还是一个Optional assertThat(Optional.of(1).map(Math::incrementExact).get(), is(2)); //通过filter实现Optional中数据的过滤,得到一个Optional,然后级联使用orElse提供默认值 assertThat(Optional.of(1).filter(integer -> integer % 2 == 0).orElse(null), is(nullValue())); //通过orElseThrow实现无数据时抛出异常 Optional.empty().orElseThrow(IllegalArgumentException::new); } image.png 3. Map接口 Map接口 putIfAbsent / computeIfAbsent/computeIfPresent 3.1 putIfAbsent

如果给定的key不存在(或者key对应的value为null),关联给定的key和给定的value,并返回null;如果存在,返回当前值(不会把value放进去);

使用场景:如果我们要变更某个key的值,我们又不知道key是否存在的情况下,而又不希望增加key的情况使用。

demo:

// 创建一个 HashMap HashMap sites = new HashMap(); // 往 HashMap 添加一些元素 sites.put(1, "Google"); sites.put(2, "Runoob"); sites.put(3, "Taobao"); System.out.println("sites HashMap: " + sites); // HashMap 不存在该key sites.putIfAbsent(4, "Weibo"); // HashMap 中存在 Key sites.putIfAbsent(2, "Wiki"); System.out.println("Updated Languages: " + sites); //结果为 sites HashMap: {1=Google, 2=Runoob, 3=Taobao} Updated sites HashMap: {1=Google, 2=Runoob, 3=Taobao, 4=Weibo} 3.2 computeIfAbsent

如果给定的 key 不存在(或者 key 对应的 value 为 null),就去计算 mappingFunction 的值;

如果 mappingFunction 的值不为 null,就把 key = value 放进去; 如果 mappingFunction 的值为 null,就不会记录该映射关系,返回值为 null; 如果计算 mappingFunction 的值的过程出现异常,再次抛出异常,不记录映射关系,返回 null;

如果存在该 key,返回的是新的 value,就算 key 对应的 value 部位 null,返回 null;(HashMap 返回的是旧 value)

default V computeIfAbsent(K key, Function


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3