【Java8新特性】不了解Optional类,简历上别说你懂Java8!! (2)

可以看到,当使用orElseGet()方法时,getDefaultName()方法并不执行,因为Optional中含有值,而使用orElse时则照常执行。所以可以看到,当值存在时,orElse相比于orElseGet,多创建了一个对象。如果创建对象时,存在网络交互,那系统资源的开销就比较大了,这是需要我们注意的一个地方。

4.orElseThrow

orElseThrow()方法当遇到一个不存在的值的时候,并不返回一个默认值,而是抛出异常。

String nullName = null; String name = Optional.ofNullable(nullName).orElseThrow( IllegalArgumentException::new); 5.get

get()方法表示是Optional对象中获取值。

Optional<String> opt = Optional.of("binghe"); String name = opt.get(); assertEquals("binghe", name);

使用get()方法也可以返回被包裹着的值。但是值必须存在。当值不存在时,会抛出一个NoSuchElementException异常。

Optional<String> opt = Optional.ofNullable(null); String name = opt.get(); 6.filter

接收一个函数式接口,当符合接口时,则返回一个Optional对象,否则返回一个空的Optional对象。

String name = "binghe"; Optional<String> nameOptional = Optional.of(name); boolean isBinghe = nameOptional.filter(n -> "binghe".equals(name)).isPresent(); assertTrue(isBinghe); boolean isBinghe001 = nameOptional.filter(n -> "binghe001".equals(name)).isPresent(); assertFalse(isBinghe001);

使用filter()方法会过滤掉我们不需要的元素。

接下来,我们再来看一例示例,例如目前有一个Person类,如下所示。

public class Person{ private int age; public Person(int age){ this.age = age; } //省略get set方法 }

例如,我们需要过滤出年龄在25岁到35岁之前的人群,那在Java8之前我们需要创建一个如下的方法来检测每个人的年龄范围是否在25岁到35岁之前。

public boolean filterPerson(Peron person){ boolean isInRange = false; if(person != null && person.getAge() >= 25 && person.getAge() <= 35){ isInRange = true; } return isInRange; }

看上去就挺麻烦的,我们可以使用如下的方式进行测试。

assertTrue(priceIsInRange1(new Peron(18))); assertFalse(priceIsInRange1(new Peron(29))); assertFalse(priceIsInRange1(new Peron(16))); assertFalse(priceIsInRange1(new Peron(34))); assertFalse(priceIsInRange1(null));

如果使用Optional,效果如何呢?

public boolean filterPersonByOptional(Peron person){ return Optional.ofNullable(person) .map(Peron::getAge) .filter(p -> p >= 25) .filter(p -> p <= 35) .isPresent(); }

使用Optional看上去就清爽多了,这里,map()仅仅是将一个值转换为另一个值,并且这个操作并不会改变原来的值。

7.map

如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()。

List<String> names = Arrays.asList("binghe001", "binghe002", "", "binghe003", "", "binghe004"); Optional<List<String>> listOptional = Optional.of(names); int size = listOptional .map(List::size) .orElse(0); assertEquals(6, size);

在这个例子中,我们使用一个List集合封装了一些字符串,然后再把这个List使用Optional封装起来,对其map(),获取List集合的长度。map()返回的结果也被封装在一个Optional对象中,这里当值不存在的时候,我们会默认返回0。如下我们获取一个字符串的长度。

String name = "binghe"; Optional<String> nameOptional = Optional.of(name); int len = nameOptional .map(String::length()) .orElse(0); assertEquals(6, len);

我们也可以将map()方法与filter()方法结合使用,如下所示。

String password = " password "; Optional<String> passOpt = Optional.of(password); boolean correctPassword = passOpt.filter( pass -> pass.equals("password")).isPresent(); assertFalse(correctPassword); correctPassword = passOpt .map(String::trim) .filter(pass -> pass.equals("password")) .isPresent(); assertTrue(correctPassword);

上述代码的含义就是对密码进行验证,查看密码是否为指定的值。

8.flatMap

与 map 类似,要求返回值必须是Optional。

假设我们现在有一个Person类。

public class Person { private String name; private int age; private String password; public Optional<String> getName() { return Optional.ofNullable(name); } public Optional<Integer> getAge() { return Optional.ofNullable(age); } public Optional<String> getPassword() { return Optional.ofNullable(password); } // 忽略get set方法 }

接下来,我们可以将Person封装到Optional中,并进行测试,如下所示。

Person person = new Person("binghe", 18); Optional<Person> personOptional = Optional.of(person); Optional<Optional<String>> nameOptionalWrapper = personOptional.map(Person::getName); Optional<String> nameOptional = nameOptionalWrapper.orElseThrow(IllegalArgumentException::new); String name1 = nameOptional.orElse(""); assertEquals("binghe", name1); String name = personOptional .flatMap(Person::getName) .orElse(""); assertEquals("binghe", name);

注意:方法getName返回的是一个Optional对象,如果使用map,我们还需要再调用一次get()方法,而使用flatMap()就不需要了。

写在最后

如果觉得文章对你有点帮助,请微信搜索并关注「 冰河技术 」微信公众号,跟冰河学习Java8新特性。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjdxz.html