将集合转换为数组的最简单方法是什么?

Rom*_*man 118 java arrays collections transformation

假设我们有一个Collection<Foo>.什么是最好的(在当前环境中最短的LoC)方式将其转换为Foo[]?任何知名的图书馆都是允许的.

UPD:(更多的情况在本节中,发表评论,如果你认为这是值得创建另一个线程它):关于什么转变Collection<Foo>Bar[]那里Bar与1个型参数有构造函数Foo,即public Bar(Foo foo){ ... }

dou*_*lep 243

x集合在哪里:

Foo[] foos = x.toArray(new Foo[x.size()]);
Run Code Online (Sandbox Code Playgroud)

  • **更简单**(更容易)但不是最好的(记忆):`x.toArray(new Foo [0])`---**文件**:没时间阅读...... (32认同)
  • 请注意,即使您使用的是同步集合,此代码也不是线程安全的.它在大多数情况下都会表现出来,但是如果在调用x.size()和x.toArray()之间删除了一个项,则结果数组的末尾将包含一个额外的null元素.卡洛斯提出的"新Foo [0]"变体不会遇到这个问题. (19认同)
  • @Carlos实际上,它比`(new Foo [0])`使用更好的内存.根据Collection.toArray文档,`@param是要存储此集合元素的数组,如果它足够大,这意味着它将直接将它们存储在新数组中.如果你给它一个0号数组,它将创建一个新数组,这意味着你有一个小数组和一个大数组,当这是不必要的. (5认同)
  • @glowcoder - 但如果将一个空数组定义为静态常量,则可以将其最小化.它只是提示`toArray`创建一个正确类型的目标数组.在这种情况下,老实说,我不关心我的应用程序中的一个额外的单个空数组.这远远低于噪音水平. (4认同)
  • @glowcoder-这就是我(*尝试*)写道,使用`new Foo [0]`更简单“但不是最好的(内存)”的原因……也就是说,我的意思是我的解决方案更简单但不是最好的(这就是我使用`:`的原因。 (2认同)

Jul*_*les 34

使用Java 8更新问题的替代解决方案:

Bar[] result = foos.stream()
    .map(x -> new Bar(x))
    .toArray(size -> new Bar[size]);
Run Code Online (Sandbox Code Playgroud)

  • 这可以缩短为`Bar [] result = foos.stream().map(Bar :: new).toArray(Bar [] :: new);` (33认同)

And*_*s_D 10

如果您多次使用它或在循环中使用它,您可以定义一个常量

public static final Foo[] FOO = new Foo[]{};
Run Code Online (Sandbox Code Playgroud)

并进行转换

Foo[] foos = fooCollection.toArray(FOO);
Run Code Online (Sandbox Code Playgroud)

toArray方法将采用空数组来确定目标数组的正确类型,并为您创建一个新数组.


这是我的更新建议:

Collection<Foo> foos = new ArrayList<Foo>();
Collection<Bar> temp = new ArrayList<Bar>();
for (Foo foo:foos) 
    temp.add(new Bar(foo));
Bar[] bars = temp.toArray(new Bar[]{});
Run Code Online (Sandbox Code Playgroud)

  • 长度为零,没有可以更改的内容 (2认同)

Nam*_*man 6

与JDK / 11,转换的替代方式Collection<Foo>,以一个Foo[]可利用的Collection.toArray(IntFunction<T[]> generator)为:

Foo[] foos = fooCollection.toArray(new Foo[0]); // before JDK 11
Foo[] updatedFoos = fooCollection.toArray(Foo[]::new); // after JDK 11
Run Code Online (Sandbox Code Playgroud)

正如@Stuart 在邮件列表(重点是我的)中所解释的那样,它的性能应该与现有的性能基本相同Collection.toArray(new T[0])——

结果是使用Arrays.copyOf() 的实现是最快的,可能是因为它是一个内在的.

它可以避免对新分配的数组进行零填充,因为它知道整个数组内容将被覆盖。无论公共 API 是什么样子,这都是正确的。

JDK 中 API 的实现内容如下:

default <T> T[] toArray(IntFunction<T[]> generator) {
    return toArray(generator.apply(0));
}
Run Code Online (Sandbox Code Playgroud)

默认实现调用generator.apply(0)获取零长度数组,然后简单地调用toArray(T[]). 这通过Arrays.copyOf() 快速路径,因此它的速度基本上与toArray(new T[0]).


注意:- 只是当用于带有值的代码时,API 的使用应与向后不兼容一起进行指导,null例如,toArray(null)因为这些调用现在由于存在toArray(T[] a)而变得不明确并且将无法编译。


And*_*nzo 5

如果您在项目中使用 Guava,则可以使用Iterables::toArray.

Foo[] foos = Iterables.toArray(x, Foo.class);
Run Code Online (Sandbox Code Playgroud)