Java Optional&Vavr Option:基本介绍

阅读: 评论:0

Java Optional&Vavr Option:基本介绍

Java Optional&Vavr Option:基本介绍

嗨,您好! 我今天想讨论一些基本的Java主题-Optional类的用法,并将其与Vavr库中的替代方法进行比较。 可选的方法最初是在Java 8中引入的,并且被定义为“可能包含也可能不包含非空值值的容器对象”。 开发人员利用Optionals以避免执行代码时对位置进行空值检查,这不是结果,而是空值价值,它可以导致空指针异常。 在这种情况下,Optional为我们提供了一些精美的功能,但并非所有功能都在第8版中引入,某些功能需要Java11。处理这些问题的另一种方法是Vavr的Option类。

在本文中,我们将学习如何使用Java Optional类,然后将其与Vavr Option类进行比较。 请注意,该代码至少需要Java 11并已通过Vavr进行了测试0。10。2。

Introducing Java Optional

Optional的概念并不是什么新鲜事物,并且已经在功能编程语言(例如Haskell或Scala)中实现。 在对方法调用可能返回未知值或不存在的值(例如null)的情况进行建模时,它被证明非常有用。 让我们看看如何处理它。

Creation of Optional

首先,我们需要获取Optional的实例。 有几种方法可以做到这一点-而且我们还可以创建一个空的可选的。 检查第一种方法-从值创建,这非常简单:

Optional<Integer> four = Optional.of(Integer.valueOf(4));
if (four.isPresent){System.out.println("Hoorayy! We have a value");
} else {System.out.println("No value");
}

我们从4的Integer值构建一个Optional,这意味着始终应该有一个值,并且它不能为null,但这只是一个示例。 我们用以下方法检查价值的存在或不存在ifPresent()方法。 您可以注意到,四不是整数,而是容器,在里面保存整数。 当我们确定该值在里面时,我们可以使用得到()方法。 具有讽刺意味的是,如果我们使用得到()无需检查,我们可以以NoSuchElementException结尾。

Another way to obtain an Optional is using streams. Several terminal stream's methods return Optionals, so we can manipulate them and checking existence or absence, for example:

  • findAnyfindFirst最高分减少

检查以下代码片段:

Optional<Car> car = cars.stream().filter(car-&Id().equalsIgnoreCase(id)).findFirst();

下一个选项是从代码创建Optional,可能产生空值,例如 来自Nullable:

Optional<Integer> nullable = Optional.RequestData());

最后,我们可以创建一个空的可选的:

Optional<Integer> nothing = pty();

How to use Optional

只要获得了Optional,就可以使用它。 一种最普遍的情况是在Spring存储库中使用它通过id查找一条记录,因此我们可以在Optional上构建逻辑并避免进行空检查(顺便说一句,Spring还支持Vavr Options)。 假设我们有一个图书库,想找到一本书。

Optional<Book> book = repository.findOne("some id");

首先,我们可以执行一些逻辑,以防万一,被表达。 我们在上一节中使用if-else做到了这一点,但是我们不需要:Optional为我们提供了一种接受消费者与对象:

repository.findOne("some id").ifPresent(book -> {});

甚至更简单,我们可以使用方法引用来编写它:

repository.findOne("some id").ifPresent(System.out::println);

如果存储库中没有书籍,则可以使用isPresent OrElseGet方法:

repository.findOne("some id").ifPresentOrElseGet(book->{// if value is presented
}, ()->{// if value is absent
});

另外,如果没有给出运算结果,我们可以得到另一个值:

Book result = repository.findOne("some id").orElse(defaultBook);

但是,使用Optionals,我们需要记住可能存在的缺点。 在最后一个示例中,我们自己“保证”我们无论如何都会得到一本书,无论是呈现在底层存储库中还是来自要不然。 但是,如果默认值不是不变,还需要一些复杂的方法吗? 首先,Java无论如何评估找一个。 然后,它必须处理要不然 method. Yes, if it is just a default 不变 value it is ok, but it can be as I said before time-consuming as well.

Let have an example

让我们创建一个简单的示例来检查实际上如何使用Optional和Option类。 我们会有一个汽车储存库会根据提供的ID(例如,车牌号)找到一辆汽车。 然后,我们将看到如何操作Optional和Options。

Add some code first

从POJO类开始汽车。 它遵循一成不变的模式,因此所有字段都是最终字段,我们只有getter,没有setter。 初始化期间将提供所有数据。

public class Car {private final String name;private final String id;private final String color;public Car (String name, String id, String color){this.name = name;this.id = lor = color;}public String getId(){return id;}public String getColor() {return color;}public String getName() {return name;}@Overridepublic String toString() {return "Car "+name+" with license id "+id+" and of color "+color;}
}

第二件事是创建汽车储存库类。 按ID查找汽车将有两个选择-使用可能产生空结果的旧方法以及使用诸如Spring存储库的Optional。

public class CarRepository {private List<Car> cars;public CarRepository(){getSomeCars();}Car findCarById(String id){for (Car car: cars){if (Id().equalsIgnoreCase(id)){return car;}}return null;}Optional<Car> findCarByIdWithOptional(String id){return cars.stream().filter(car-&Id().equalsIgnoreCase(id)).findFirst();}private void getSomeCars(){cars = new ArrayList<>();cars.add(new Car("tesla", "1A9 4321", "red"));cars.add(new Car("volkswagen", "2B1 1292", "blue"));cars.add(new Car("skoda", "5C9 9984", "green"));cars.add(new Car("audi", "8E4 4321", "silver"));cars.add(new Car("mercedes", "3B4 5555", "black"));cars.add(new Car("seat", "6U5 3123", "white"));}
}

注意,在初始化过程中,我们还会用一些模拟汽车填充存储库,因此我们没有任何底层数据库。 我们需要避免复杂性,让我们专注于Optional和Option,而不是存储库。

Finding cars with Java Optional

Create a new test with JUnit (I also have an excellent tutorial on JUnit 5 if you don't have experience with it).

@Test
void getCarById(){Car car = repository.findCarById("1A9 4321");Assertions.assertNotNull(car);Car nullCar = repository.findCarById("M 432 KT");Assertions.assertThrows(NullPointerException.class, ()->{if (nullCar == null){throw new NullPointerException();}});
}

此代码段演示了旧方法。 我们找到了一辆带捷克车牌的汽车1A9 4321并检查它是否存在。 然后我们发现一辆缺少的车,因为它有俄罗斯的车牌,而我们的仓库里只有捷克的车。 它是空值,因此可能会导致NullPointerException。

接下来,让我们转到Java Optionals。 第一步是使用返回Optional的专用方法从存储库获取Optional实例:

@Test
void getCarByIdWithOptional(){Optional<Car> tesla = repository.findCarByIdWithOptional("1A9 4321");tesla.ifPresent(System.out::println);
}

在这种情况下,我们使用findCarByIdWithOptional方法,然后打印汽车(如果有)。 如果运行它,将得到以下输出:

Car tesla with license id 1A9 4321 and of color red

但是,如果我们的代码中没有该特殊方法,该怎么办? 在这种情况下,我们可以从可能会返回空值的方法中获取Optional。 叫做可为空:

Optional<Car> nothing = Optional.ofNullable(repository.findCarById("5T1 0965"));
Assertions.assertThrows(NoSuchElementException.class, ()->{Car car = ElseThrow(()->new NoSuchElementException());
});

在此代码段中,我们使用另一种方式。 我们从创建可选findCarById可以返回空值如果找不到车。 我们手动使用否则带有牌照的所需汽车时抛出NoSuchElementException的方法5T1 0965存在。 另一种情况是使用要不然带有一些默认值,如果请求的数据在存储库中不可用:

Car audi = repository.findCarByIdWithOptional("8E4 4311").orElse(new Car("audi", "1W3 4212", "yellow"));if (Color().equalsIgnoreCase("silver")){System.out.println("We have silver audi in garage!");} else {System.out.println("Sorry, there is no silver audi, but we called you a taxi");
}

好的,我们的车库里没有银色的奥迪,所以我们必须叫出租车!

Finding cars with Vavr Option

Vavr Option是处理这些任务的另一种方法。 首先,使用依赖项管理在您的项目中安装Vavr(我使用Maven):

<dependency><groupId>io.vavr</groupId><artifactId>vavr</artifactId><version>0.10.2</version>
</dependency>

简而言之,Vavr具有类似的API以创建Option实例。 我们可以从nullable创建Option:

Option<Car> nothing = Option.of(repository.findCarById("T 543 KK"));

或者我们可以创建一个空的带有容器没有静态方法:

Option<Car> nullable = ();

另外,还有一种方法可以从Java Optional创建Option! 看一下下面的代码片段:

Option<Car> result = Option.ofOptional(repository.findCarByIdWithOptional("5C9 9984"));

使用Vavr Option,我们可以使用与Optional相同的API,并完成上述任务。 例如,我们可以通过类似的方式设置默认值:

Option<Car> result = Option.ofOptional(repository.findCarByIdWithOptional("5C9 9984"));
Car skoda = OrElse(new Car("skoda", "5E2 4232", "pink"));
System.out.println(skoda);

或者我们可以根据缺少请求的数据而引发异常:

Option<Car> nullable = ();
Assertions.assertThrows(NoSuchElementException.class, ()->{OrElseThrow(()->new NoSuchElementException());
});

或者,当数据不可用时,我们可以执行以下操作:

///runnable
})

如果我们需要根据数据的存在执行操作,该怎么办,就像我们对Optional所做的那样ifPresent? 我们可以通过几种方式做到这一点。 有一个平等的方法存在在Optional中调用被定义为:

if (result.isDefined()){// do something
}

但是,我们使用Option摆脱了if-else构造。 能否以与Optional相同的方式浮动? 我们可以根据存在与否执行操作窥视:

result.peek(val -> System.out.println(val)).onEmpty(() -> System.out.println("Result is missed"));

Also, there are some other very useful methods in Vavr Option that gonna make your code much more functional, than with built-in Optional class. So I encourage you to take some time and explore Vavr Option javadocs and experiment with these APIs. I can note some cool things like map, narrow, isLazy and when that you definetly need to check out. Also, Vavr Option is a part of Vavr family and is heavily integrated with Vavr other classes, and make such comparasion with Optional in vaccuum, e.g. in abscence of such classes is not correct. So, I would also write posts on other Vavr topics, like Try, Collections, Streams. Don't forget to sign up for updates!

Conclusion

在本文中,我们讨论了Java中的Optional类。 Optional的概念并不是什么新鲜事物,并且已经在功能编程语言(例如Haskell或Scala)中实现。 在对方法调用可能返回未知值或不存在的值(例如null)的情况进行建模时,它被证明非常有用。 让我们看看如何处理它。 我们探索了其API,并提供了一些示例,以查找汽车并使用Optional逻辑处理结果。 然后,我们发现了Optional-Vavr's Option的替代方法,并描述了其方法。

Read more

  • José Paumard. Optionals: Patterns and Good Practices (2016) Oracle Community Directory, read here
  • Mervyn McCreight and Mehmet Emin Tok. A look at the Optional datatype in Java and some anti-patterns when using it (2019) FreeCodeCamp, read here
  • Radosław Nowak. Functional programming in Java with Vavr (2018) Pragmatists, read here

from: //andreevich/java-optional-vavr-option-an-essential-introduction-10cb

本文发布于:2024-01-29 12:39:22,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170650316615344.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:Optional   Java   Option   Vavr
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23