[英]How to convert Optional<List<Integer>> to Optional<ArrayList<Integer>>
I've tried to do the following, but it doesn't work我尝试执行以下操作,但它不起作用
Optional<List<Integer>> listOne = someAPI.call()
// convert
Optional<ArrayList<Integer>> listTwo = new ArrayList<>(listOne); // doesn't work
Optional<ArrayList<Integer>> listTwo = Optional.of(new ArrayList(listOne)); // also not working
Note that the first API returns Optional<List>
.请注意,第一个 API 返回
Optional<List>
。 And I need to send Optional<ArrayList>
to another API.我需要将
Optional<ArrayList>
发送到另一个 API。
By making use of Optional<ArrayList<Integer>>
you piggyback one contrived problem on top of the other.通过使用
Optional<ArrayList<Integer>>
您可以将一个人为的问题放在另一个之上。
Any Collection
by itself could represent the absence of data by being empty .任何
Collection
本身都可以通过为空来表示数据的缺失。 And you can safely interact with an empty collection.您可以安全地与空集合进行交互。 Wrapping it with an
Optional
is redundant.用
Optional
包装它是多余的。
Here is a quote from the answer by Brian Goetz , Java language Architect, regarding how the Optional
is intended to be used, and how it shouldn't be used from the perspective of its creators:这里引用了Brian Goetz的回答,Java 语言架构师,关于
Optional
的使用方式,以及从其创建者的角度来看不应该如何使用它:
Our intention was to provide a limited mechanism for library method return types where there needed to be a clear way to represent "no result" , and using
null
for such was overwhelmingly likely to cause errors.我们的目的是为库方法返回类型提供一种有限的机制,在这种情况下需要一种明确的方式来表示“无结果” ,并且使用
null
有可能导致错误。For example, you probably should never use it for something that returns an array of results, or a list of results;
例如,您可能永远不应该将它用于返回结果数组或结果列表的东西; instead return an empty array or list .
而是返回一个空数组或列表。
Conclusion: design of the first API returning Optional<List<Integer>>
is incorrect.结论:第一个 API 返回
Optional<List<Integer>>
的设计不正确。
This considered a misuse of the Optional because it goes against the main design goal of Optional (see the quote above, also have a look at the answer by Stuart Marks , Java and OpenJDK developer).这被认为是对 Optional 的滥用,因为它违背了 Optional 的主要设计目标(请参阅上面的引文,也可以看看Stuart Marks 、Java 和 OpenJDK 开发人员的答案)。
Conclusion: design of the second API expecting Optional<ArrayList<Integer>>
is also wrong.结论:期望
Optional<ArrayList<Integer>>
的第二个 API 的设计也是错误的。
Leverage abstractions, write your code against interfaces.利用抽象,针对接口编写代码。 There's no justification for making the code inflexible and capable only of consuming instances of
ArrayList
because it would not be able to deal with a List
produced by Collections.emptyList()
, List.of()
, Arrays.asList()
, Stream.toList()
, etc. There's no justification for making the code inflexible and capable only of consuming instances of
ArrayList
because it would not be able to deal with a List
produced by Collections.emptyList()
, List.of()
, Arrays.asList()
, Stream.toList()
等。
See What does it mean to "program to an interface"?请参阅“编程到接口”是什么意思?
Fix both endpoints if you can.如果可以,修复两个端点。 Make them work without
Optional
.让它们在没有
Optional
的情况下工作。
In case if you're not in control of this first API returning the optional, fine, then don't make the problem bigger - fix the second API, make it expect a list of integer.如果您无法控制第一个 API 返回可选的,很好,那么不要让问题变得更大 - 修复第二个 API,让它期待 Z157DB7DF530023575515D366C9B672 的列表。 And unpack the optional result right on the spot before call the second API.
并在调用第二个 API 之前当场解压可选结果。
You can use orElse()
for that purpose:您可以为此目的使用
orElse()
:
List<Integer> list = someAPI.call().orElse(Collections.emptyList());
If you can't change both APIs, then you're out of lack.如果你不能同时改变这两个 API,那么你就完蛋了。
Also, not that listOne.map(ArrayList::new)
creates a copy of the initial data, that means that your system instead of making the second call immediately is forced to perform an additional step because of poor API design.此外,不是
listOne.map(ArrayList::new)
创建初始数据的副本,这意味着由于 API 设计不佳,您的系统不会立即进行第二次调用,而是被迫执行额外的步骤。
If you start with this:如果你从这个开始:
Optional<List<Integer>> optionalList = getFromSomewhere();
You can convert to Optional<ArrayList<Integer>>
like this:您可以像这样转换为
Optional<ArrayList<Integer>>
:
Optional<ArrayList<Integer>> optionalArrayList = Optional.of(new ArrayList<>(optionalList.get()));
This is close to what you tried - Optional.of(new ArrayList(listOne))
– but your attempt didn't work because listOne
is type Optional<List<Integer>>
, whereas the constructor to new ArrayList()
takes a Collection.这与您尝试的接近 -
Optional.of(new ArrayList(listOne))
- 但您的尝试没有奏效,因为listOne
的类型是Optional<List<Integer>>
,而new ArrayList()
的构造函数需要一个集合。 If you call .get()
then you'll get the list out of the Optional, and that works fine for the ArrayList constructor.如果您调用
.get()
,那么您将从 Optional 中获取列表,这对于 ArrayList 构造函数可以正常工作。
您可以像这样转换它:
Optional<ArrayList<Integer>> listTwo = listOne.map(ArrayList::new);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.