英文:
Use Java8 map over Optional.Empty()
问题
我有一段代码,其中我正在做如下操作:
```java
Optional<College> college = Optional.ofNullable(student)
.map(stud -> stud.getCollege())
.get()
.stream()
.filter(college -> Objects.nonNull(college.getCollegeName()))
.findFirst();
现在,在编写单元测试时,我遇到了一个问题,如果student为null
怎么办?
它将有效地变成:
Optional.empty() // 与student为null相同
.map(stud -> stud.getCollege())
.get()
.stream()
.filter(college -> Objects.nonNull(college.getCollegeName()))
.findFirst();
我认为这不好,因为我得到了异常
expected<com.src.exceptions.CollegeNotFoundException> but
was<java.util.NoSuchElementException>
#更新
为了澄清问题详情
- 是的,stud.getCollege()返回一个list<>
<details>
<summary>英文:</summary>
I have a piece of code where am doing something like:
```java
Optional<College> college = Optional.ofNullable(student)
.map(stud -> stud.getCollege())
.get()
.stream()
.filter(college -> Objects.nonNull(college.getCollegeName()))
.findFirst();
Now, while writing an unit test, I got a catch that what if student comes as null
?
It would be effectively like:
Optional.empty() // the same as the student is null
.map(stud -> stud.getCollege())
.get()
.stream()
.filter(college -> Objects.nonNull(college.getCollegeName()))
.findFirst();
Which I think is not fine because I am getting Exception
expected<com.src.exceptions.CollegeNotFoundException> but
was<java.util.NoSuchElementException>
#Update
Updating the question details for clarifications
- Yes stud.getCollege() returns a list<>
答案1
得分: 3
我同意@Nikolas的方法,除非你不应该返回null
,在最后返回null
违反了使用Optional
。对于这个代码片段,可以翻译如下:
Optional<College> optional = Optional.ofNullable(student)
.map(stud -> stud.getCollegeList())
.orElse(Collections.emptyList())
.stream()
.filter(c -> Objects.nonNull(c.getCollegeName()))
.findFirst();
英文:
I agree with @Nikolas approach except that you should not return null
, returning null
at last is against using Optional
What about this one:
Optional<College> optional = Optional.ofNullable(student)
.map(stud -> stud.getCollegeList())
.orElse(Collections.emptyList())
.stream()
.filter(c -> Objects.nonNull(c.getCollegeName()))
.findFirst();
答案2
得分: 1
使用没有先前检查 Optional::isPresent
的方式调用 Optional::get
是危险的,因为它可能会产生 CollegeNotFoundException
。这也不是使用 Optional
的正确方式。Optional
的理念是在映射/筛选值并在 Optional
最终为空(空)时提供一个默认值。
假设 Student::getCollege
返回 List<College>
,其中有一个方法 College::getCollegeName
,你可以这样做:
College college = Optional.ofNullable(student)
.map(stud -> stud.getCollege())
// 如果 Optional 为空,则使用一个空集合
.orElse(Collections.emptyList())
.stream()
.filter(c -> Objects.nonNull(c.getCollegeName()))
.findFirst()
// 获取值,否则 college 为 null
.orElse(null);
只要 stud.getCollege()
返回 null
,Optional
就会变为空,然后将会流式处理一个空列表。再次应用相同的原则:只要列表为空,就不会调用 filter
和 findFirst
,安全地返回 null
(或者你希望的任何默认值)。
还请注意,.filter(c -> Objects.nonNull(c.getCollegeName()))
这一行可能也会产生 NullPointerException
,只要不能保证 stud.getCollege()
不会返回带有 null
元素的列表(请记住,列表本身不为 null
,所以 Optional
将其视为一个有价值的项)。安全的代码实际上看起来像这样:
Optional<College> college = Optional.ofNullable(student)
.map(stud -> stud.getCollege())
.orElse(Collections.emptyList())
.stream()
.filter(c -> c != null && c.getCollegeName() != null)
.findFirst();
实际上,我更喜欢返回 null 对象、null
或 Optional
本身。
英文:
Calling Optional::get
with no previous check Optional::isPresent
is dangerous because it might produce CollegeNotFoundException
. And it is not the way the Optional
shall be used. The idea of Optional
is mapping/filtering the values and providing a default value if the Optional
ends up with no element (empty).
Assuming Student::getCollege
returns List<College>
having method College::getCollegeName
, you can do the following:
College college = Optional.ofNullable(student)
.map(stud -> stud.getCollege())
// if Optional is empty, then use an empty collection
.orElse(Collections.emptyList())
.stream()
.filter(c -> Objects.nonNull(c.getCollegeName()))
.findFirst()
// get the value or else college is null
.orElse(null);
As long as stud.getCollege()
returns null
, the Optional
becomes empty and an empty list will be streamed. And again the same principle is applied: As long as the list is empty, the filter
and findFirst
are not be called and null
is safely returned (or any default value you wish).
Also note that the line .filter(c -> Objects.nonNull(c.getCollegeName()))
might also produce NullPointerException
as long as there is not guaranteed stud.getCollege()
doesn't return a list with a null
element (remember the list is not null
itself so Optional
treats it as a "valuable" item). The safe code actually looks like:
Optional<College> college = Optional.ofNullable(student)
.map(stud -> stud.getCollege())
.orElse(Collections.emptyList())
.stream()
.filter(c -> c != null && c.getCollegeName() != null)
.findFirst();
Actually, I prefer to return either a null-object, null
or Optional
itself.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论