在一行中初始化 ArrayList

问:

我想创建一个用于测试目的的选项列表。起初,我是这样做的:

ArrayList places = new ArrayList();
places.add("Buenos Aires");
places.add("Córdoba");
places.add("La Plata");

然后,我将代码重构如下:

ArrayList places = new ArrayList(
    Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));

有一个更好的方法吗?

答1:

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

如果您只是将其声明为 List 会更简单 - 它必须是 ArrayList 吗?

List places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");

或者,如果您只有一个元素:

List places = Collections.singletonList("Buenos Aires");

这意味着 places 是不可变的(尝试更改它会导致抛出 UnsupportedOperationException 异常)。

要创建一个具体 ArrayList 的可变列表,您可以从不可变列表创建一个 ArrayList:

ArrayList places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));

并导入正确的包:

import java.util.Arrays;

是的,我的班级有一个私有的 ArrayList。

@Marcase:你能不能改变你的类来使用 List 而不是 ArrayList?

根据我的回答,如果您不使用特定于 ArrayList 的方法,最好将声明更改为 List。指定接口,而不是实现。

@Christoffer Hammarström:如果他将声明更改为 List 并使用 List places = Arrays.asList(...);他将无法使用 places.add("blabla")

需要明确的是,asList(...) 返回一个固定大小的 List,它会在 remove 和 clear 之类的变异操作上崩溃,而 List 合约声称支持这些操作。即使您将声明保留为 List,您仍然需要使用 List l = new ArrayList(asList(...)) 来获取不会引发 OperationNotSupported 异常的对象。里斯科夫替换原则有人吗?

答2:

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

实际上,初始化 ArrayList 的“最佳”方法可能是您编写的方法,因为它不需要以任何方式创建新的 List:

ArrayList list = new ArrayList();
list.add("A");
list.add("B");
list.add("C");

需要注意的是,要引用该 list 实例需要进行大量输入。

还有其他选择,例如使用实例初始化器创建匿名内部类(也称为“双括号初始化”):

ArrayList list = new ArrayList() {{
    add("A");
    add("B");
    add("C");
}};

但是,我不太喜欢这种方法,因为您最终得到的是 ArrayList 的一个子类,它有一个实例初始化程序,并且创建该类只是为了创建一个对象——这似乎有点矫枉过正大部头书。

如果 Project Coin 的 Collection Literals proposal 被接受,那会更好(它计划在 Java 7 中引入,但它也不太可能成为 Java 8 的一部分。):

List list = ["A", "B", "C"];

不幸的是,它在这里对您没有帮助,因为它会初始化一个不可变的 List 而不是 ArrayList,而且,它还不可用,如果有的话。

有关双括号初始化、优缺点的更多信息,请参阅 stackoverflow.com/questions/924285。

您不需要第二个 。

答3:

huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。

简单的答案

Java 9 或更高版本:

List strings = List.of("foo", "bar", "baz");

这将为您提供一个不可变 List,因此它无法更改。在大多数情况下,这是您预填充它时想要的。

Java 8 或更早版本:

List strings = Arrays.asList("foo", "bar", "baz");

这将为您提供一个由数组支持的 List*,因此它无法更改长度。但您可以调用 List.set(…),因此它仍然是可变。

  • 实现细节:它是 java.util.Arrays 内的私有嵌套类,名为 ArrayList, 与 java.util.ArrayList 不同,尽管它们的简单名称相同。

静态导入

您可以使用静态导入使 Java 8 Arrays.asList 更短:

import static java.util.Arrays.asList;  
...
List strings = asList("foo", "bar", "baz");

任何现代 IDE* 都会建议并为您执行此操作。

我不建议将 List.of 方法静态导入为 of,因为它会造成混淆。

  • 例如,在 IntelliJ IDEA 中按 Alt+Enter 并选择 Static import method…

使用流

为什么它必须是 List?在 Java 8 或更高版本中,您可以使用更灵活的 Stream:

Stream strings = Stream.of("foo", "bar", "baz");

您可以连接 Stream:

Stream strings = Stream.concat(Stream.of("foo", "bar"),
                                       Stream.of("baz", "qux"));

或者您可以从 Stream 转到 List:

import static java.util.stream.Collectors.toList;
...
var strings = Stream.of("foo", "bar", "baz").toList(); // Java 16

List strings = Stream.of("foo", "bar", "baz").collect(toList()); // Java 8

但最好只使用 Stream 而不将其收集到 List。

如果您特别需要 java.util.ArrayList*

如果您想 both 预填充一个 ArrayList 并 然后添加到它,请使用

List strings = new ArrayList<>(List.of("foo", "bar"));
strings.add("baz");

或在 Java 8 或更早版本中:

List strings = new ArrayList<>(asList("foo", "bar"));
strings.add("baz");

或使用 Stream:

import static java.util.stream.Collectors.toCollection;

List strings = Stream.of("foo", "bar")
                             .collect(toCollection(ArrayList::new));
strings.add("baz");

但同样,最好直接使用 Stream,而不是将其收集到 List。

*您可能不需要专门的 ArrayList。引用 JEP 269:

有一小部分用例用于使用一组预定义的值初始化可变集合实例。通常最好将这些预定义值放在不可变集合中,然后通过复制构造函数初始化可变集合。

(强调我的)

编程接口,而不是实现

您说您已在代码中将列表声明为 ArrayList,但只有在使用不在 List 中的 ArrayList 的某些成员时才应这样做。

您很可能不会这样做。

通常您应该只通过您将要使用的最通用接口(例如 Iterable、Collection 或 List)声明变量,并使用特定实现(例如 ArrayList、LinkedList 或Arrays.asList())。

否则,您会将代码限制为该特定类型,并且在您想要更改时会更难。

例如,如果您将 ArrayList 传递给 void method(…):

// Iterable if you just need iteration, for (String s : strings):
void method(Iterable strings) { 
    for (String s : strings) { ... } 
}

// Collection if you also need .size(), .isEmpty(), or .stream():
void method(Collection strings) {
    if (!strings.isEmpty()) { strings.stream()... }
}

// List if you also need random access, .get(index):
void method(List strings) {
    strings.get(...)
}

// Don't declare a specific list implementation
// unless you're sure you need it:
void method(ArrayList strings) {
    ??? // You don't want to limit yourself to just ArrayList
}

另一个示例总是将变量声明为 InputStream,即使它通常是 FileInputStream 或 BufferedInputStream,因为不久之后您或其他人会想要使用某种其他类型的 InputStream。

与HuntsBot一起,探索全球自由职业机会–huntsbot.com

答4:

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

如果您需要大小为 1 的简单列表:

List strings = new ArrayList(Collections.singletonList("A"));

如果您需要多个对象的列表:

List strings = new ArrayList();
Collections.addAll(strings,"A","B","C","D");

答5:

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

使用 Guava,您可以编写:

ArrayList places = Lists.newArrayList("Buenos Aires", "Córdoba", "La Plata");

在 Guava 中还有其他有用的静态构造函数。您可以阅读它们here。

我很确定您只需使用 java.util.Arrays(例如 List names = Arrays.asList("Beckah", "Sam", "Michael");)就可以做到这一点

@beckah 方法 Arrays.asLists 创建 List 类型的对象,而问题是关于创建 ArrayList

This method is not actually very useful and will likely be deprecated in the future.

@beckah Arrays.asList 创建一个无法修改的列表。如果需要修改列表,Lists.newArrayList 将起作用,而 Arrays.asList 将不起作用。

答6:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

使用 java-9 及更高版本,如 JEP 269: Convenience Factory Methods for Collections 中所建议的,这可以使用 collection literals 现在与 -

List list = List.of("A", "B", "C");

Set set = Set.of("A", "B", "C");

类似的方法也适用于 Map -

Map map = Map.of("k1", "v1", "k2", "v2", "k3", "v3")

这类似于@coobird 所述的Collection Literals proposal。 JEP中也进一步澄清了 -

备择方案

语言更改已被考虑多次,但被拒绝: Project Coin 提案,2009 年 3 月 29 日 Project Coin 提案,2009 年 3 月 30 日 JEP 186 关于 lambda-dev 的讨论,2014 年 1 月至 3 月此消息中总结的建议。

相关:What is the point of overloaded Convenience Factory Methods for Collections in Java 9

答7:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

集合文字没有进入 Java 8,但可以使用 Stream API 在一行相当长的行中初始化一个列表:

List places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toList());

如果您需要确保您的 List 是 ArrayList:

ArrayList places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toCollection(ArrayList::new));

答8:

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

import com.google.common.collect.ImmutableList;

....

List places = ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");

我不想为此添加新的依赖项。

这与 Collections.unmodifiableList(Arrays.asList("Buenos Aires", "Córdoba", "La Plata")) 相同,它在静态导入时变为 unmodifiableList(asList("Buenos Aires", "Córdoba", "La Plata"))。你不需要谷歌收藏。

不,不一样。由于 ImmutableList 在 unmodifiableList 伪装成普通列表时,它在结果类型中记录了它的不变性。

除了不可变的,谷歌集合还提供可变数组列表: List = Lists.newArrayList("Buenos Aires", "Córdoba", "La Plata");

您要将该 ImmutableList 传递给采用 List 的其他方法,然后无论如何您都会丢失该文档。

答9:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

您可以创建一个工厂方法:

public static ArrayList createArrayList(String ... elements) {
  ArrayList list = new ArrayList();
  for (String element : elements) {
    list.add(element);
  }
  return list;
}

....

ArrayList places = createArrayList(
  "São Paulo", "Rio de Janeiro", "Brasília");

但这并不比您的第一次重构好多少。

为了获得更大的灵活性,它可以是通用的:

public static  ArrayList createArrayList(T ... elements) {
  ArrayList list = new ArrayList();
  for (T element : elements) {
    list.add(element);
  }
  return list;
}

回头看看原来的帖子,它要求在一行中进行数组初始化,而不是另外 7 行。

@LeoHolanda:我同意,为每件小事创建工厂方法太多了。但是根据情况以及该方法将要使用的次数,创建它可能是有意义的。创建额外的抽象层旨在通过创建更有意义的方法来捕捉设计者的意图来消除复杂性。

我认为我们可以将增强的 for 替换为 Collections.addAll(elements),如 here 所述。

答10:

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

在 Java 9 中,我们可以在一行中轻松地初始化 ArrayList:

List places = List.of("Buenos Aires", "Córdoba", "La Plata");

或者

List places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));

Java 9 的这种新方法与以前的方法相比具有许多优点:

空间效率不变性线程安全

有关更多详细信息,请参阅此帖子-> What is the difference between List.of and Arrays.asList?

答11:

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

只需使用以下代码,如下所示。

List list = new ArrayList() {{
            add("A");
            add("B");
            add("C");
}};

原文链接:https://www.huntsbot.com/qa/JAej/initialization-of-an-arraylist-in-one-line?lang=zh_CN&from=csdn

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值