我想创建一个用于测试目的的选项列表 . 起初,我这样做了:
ArrayList<String> places = new ArrayList<String>();
places.add("Buenos Aires");
places.add("Córdoba");
places.add("La Plata");
然后我重构代码如下:
ArrayList<String> places = new ArrayList<String>(
Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
有一个更好的方法吗?
30 回答
这是代码AbacusUtil
声明:我是AbacusUtil的开发人员 .
您可以创建工厂方法:
但它并不比你的第一次重构好多少 .
为了更大的灵活性,它可以是通用的:
这是
Arrays.asList
的实现,所以你可以去喜欢Tom said:
但是既然你抱怨想要一个ArrayList,你应该首先知道ArrayList是List的子类,你可以简单地添加这一行:
虽然,这可能会让你抱怨'表现' .
在这种情况下,它对我来说没有意义,为什么,因为您的列表是预定义的,它没有被定义为数组(因为在初始化时已知大小) . 如果那是你的选择:
如果您不关心次要的性能差异,那么您也可以非常简单地将数组复制到ArrayList:
好的,但是将来你需要的不仅仅是地名,还需要国家代码 . 假设这仍然是一个在运行时永远不会改变的预定义列表,那么使用
enum
集合是合适的,如果将来需要更改列表,则需要重新编译 .会成为:
枚举有一个静态
values
方法,它返回一个数组,其中包含枚举的所有值,例如:在这种情况下,我猜你不需要你的ArrayList .
附: Randyaa demonstrated另一个使用静态实用程序方法Collections.addAll的好方法 .
为什么不做一个简单的实用功能呢?
“
ll
" stands for "文字列表” .(应该是评论,但是太长了,所以新回复) . 正如其他人提到的那样,
Arrays.asList
方法是固定大小的,但是's not the only issue with it. It also doesn' t非常好地处理继承 . 例如,假设您有以下内容:上面导致编译器错误,因为
List<B>
(这是Arrays.asList返回的内容)不是List<A>
的子类,即使您可以将类型B的对象添加到List<A>
对象 . 要解决这个问题,您需要执行以下操作:这可能是最好的方法,特别是 . 如果你需要一个无界的列表或需要使用继承 .
关于最紧凑的方法是:
您可以使用Cactoos中的
StickyList
:Java 9具有以下创建不可变列表的方法:
如果需要,它很容易适应创建一个可变列表:
类似的方法可用于
Set
和Map
.使用Eclipse Collections(以前为GS Collections),您可以编写以下内容:
您还可以更具体地了解类型以及它们是Mutable还是Immutable .
你也可以用套装和包包做同样的事情:
Note: 我是Eclipse Collections的提交者 .
使用Guava,你可以写:
在Guava中还有其他有用的静态构造函数 . 你可以阅读他们here .
最好的方法:
只需创建一个可以包含任意数量元素的函数,并调用它将它们添加到一行中 .
实际上,初始化
ArrayList
的方法可能是你编写的方法,因为它不需要以任何方式创建新的List
:问题是,引用
list
实例需要进行相当多的输入 .还有其他选择,例如使用实例初始化程序创建匿名内部类(也称为“双括号初始化”):
但是,我不太喜欢那个方法,因为你最终得到的是
ArrayList
的一个子类,它有一个实例初始化器,并且创建该类只是为了创建一个对象 - 这对我来说似乎有点过分 .如果Project Coin为Project Coin被接受(它将在Java 7中引入,但它也不可能成为Java 8的一部分),本来会很好的 . ):
不幸的是,它不会帮助你,因为它会初始化一个不可变的
List
而不是ArrayList
,而且,它还没有,如果有的话 .简单的答案
在Java 8或更早版本中:
这将为您提供由数组支持的
List
,因此无法更改长度 .但是你可以调用
List.set
,所以它仍然是可变的 .在Java 9中:
这将为您提供一个不可变的
List
,因此无法更改 .在您预先填充它的大多数情况下,这是您想要的 .
答案较短
您可以使用静态导入使
Arrays.asList
更短:静态导入:
任何现代IDE都会建议并自动为您做 .
例如,在IntelliJ IDEA中,按
Alt+Enter
并选择Static import method...
.但是,我不建议缩短Java 9
List.of
方法,因为只有of
会变得混乱 .List.of
已经够短了,读起来也不错 .使用流
为什么它必须是
List
?使用Java 8或更高版本,您可以使用更灵活的
Stream
:你可以连接
Stream
:或者你可以从
Stream
到List
:但最好只使用
Stream
而不将其收集到List
.如果你真的特别需要一个java.util.ArrayList
(你可能没有 . )
引用JEP 269(强调我的):
如果您想预先填充
ArrayList
并在之后添加(为什么?),请使用或者在Java 9中:
或使用
Stream
:但同样,最好直接使用
Stream
而不是将其收集到List
.编程到接口,而不是实现
你说你已经在你的代码中将列表声明为
ArrayList
,但是如果你使用ArrayList
中不属于List
的某个成员,你应该这样做 .你很可能不会这样做 .
通常,您应该通过您将要使用的最通用接口声明变量(例如
Iterable
,Collection
或List
),并使用特定实现(例如ArrayList
,LinkedList
或Arrays.asList()
)对它们进行初始化 .否则,您将代码限制为特定类型,并且在您需要时更难更改 .
例如:
另一个例子总是声明变量
InputStream
,即使它通常是FileInputStream
或BufferedInputStream
,因为有一天你或其他人会想要使用其他类型的InputStream
.实际上,可以在一行中完成:
在Java 9中,我们可以在一行中轻松初始化
ArrayList
:要么
Java 9的这种新方法与以前的方法相比具有许多优点:
Space Efficiency
Immutability
Thread Safe
有关更多详细信息,请参阅此帖子 - > What is the difference between List.of and Arrays.asList?
集合文字没有进入Java 8,但是可以使用Stream API在一个相当长的行中初始化列表:
如果您需要确保
List
是ArrayList
:您可以使用以下语句:
代码段:
对我来说,Arrays.asList()是最好的和最方便的 . 我总是喜欢这样初始化 . 如果您是Java Collections的初学者,那么我希望您参考ArrayList initialization
如果你需要一个 one item 的清单!
集合来自java.util包 .
使用
Java 9
,如JDK Enhancement Proposal - 269中所建议的那样,现在可以使用集合文字来实现 -同样类似的方法也适用于
Map
-这与@coobird所述的Collection Literals proposal相似 . 在JEP文件中进一步澄清 -
Alternatives
进一步阅读=> What is the point of overloaded Convenience Factory Methods for Collections in Java 9
如果你只是将它声明为
List
会更简单 - 它必须是一个ArrayList吗?或者,如果您只有一个元素:
这意味着
places
是 immutable (尝试更改它将导致抛出UnsupportedOperationException
异常) .要创建一个具体
ArrayList
的可变列表,您可以从不可变列表中创建ArrayList
:是的,在数组的帮助下,您可以在一行中初始化数组列表,
只需使用以下代码如下 .
这是另一种方式:
在Java中,你做不到
正如所指出的,你需要进行双支撑初始化:
但这可能会迫使您添加注释
@SuppressWarnings("serial")
或生成令人讨厌的串行UUID . 大多数代码格式化程序也会将其解包为多个语句/行 .或者你也可以
但是你可能想做一个
@SuppressWarnings("unchecked")
.另外根据javadoc你应该能够做到这一点:
但我无法用JDK 1.6编译它 .
如果您需要一个大小为1的简单列表:
如果你需要几个对象的列表:
尝试使用此代码行: