简体   繁体   English

如何转换可选<list<integer> &gt; 到可选<arraylist<integer> &gt; </arraylist<integer></list<integer>

[英]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>>您可以将一个人为的问题放在另一个之上。

Don't wrap Collections with Optional不要用可选包装 Collections

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>>的设计不正确。

Don't use Optional as an Argument不要使用 Optional 作为参数

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 的设计也是错误的。

Write your code against Interfaces针对接口编写代码

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"?请参阅“编程到接口”是什么意思?

Fixing the problem解决问题

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM