将数组转换为列表

时间:2015-05-08 11:14:07

标签: arrays java-8

为了将Integer数组转换为整数列表,我尝试了以下方法:

  1. 初始化列表(整数类型),遍历数组并插入列表

  2. 使用Java 8 Streams:

    int[] ints = {1, 2, 3};
    List<Integer> list = new ArrayList<Integer>();
    Collections.addAll(list, Arrays.stream(ints).boxed().toArray(Integer[]::new));
    
  3. 在性能方面哪个更好?

9 个答案:

答案 0 :(得分:44)

第二个创建一个新的整数数组(第一次传递),然后将这个新数组的所有元素添加到列表中(第二次传递)。因此它的效率低于第一个,它只进行一次通过,并且不会创建一个不必要的整数数组。

使用流的更好方法是

List<Integer> list = Arrays.stream(ints).boxed().collect(Collectors.toList());

与第一个应该具有大致相同的性能。

请注意,对于如此小的阵列,不会有任何显着差异。您应该尝试编写正确,可读,可维护的代码,而不是关注性能。

答案 1 :(得分:42)

只需尝试类似

的内容
Arrays.asList(array)

答案 2 :(得分:11)

如果您不想更改列表:

List<Integer> list = Arrays.asList(array)

但是如果你想修改它,那么你可以使用它:

List<Integer> list = new ArrayList<Integer>(Arrays.asList(ints));

或者只使用 java8 ,如下所示:

List<Integer> list = Arrays.stream(ints).collect(Collectors.toList());

Java9 引入了这种方法:

List<Integer> list = List.of(ints);

但是,这将返回一个无法添加的不可变列表。

您需要执行以下操作才能使其变为可变:

List<Integer> list = new ArrayList<Integer>(List.of(ints));

答案 3 :(得分:1)

如果您正在处理String []而不是int [],我们可以使用

ArrayList<String> list = new ArrayList<>();
list.addAll(Arrays.asList(StringArray));

答案 4 :(得分:1)

如果您不介意第三方依赖,您可以使用本机支持原始集合的库,如Eclipse Collections,并完全避免装箱。如果需要,您还可以使用原始集合来创建盒装常规集合。

int[] ints = {1, 2, 3};
MutableIntList intList = IntLists.mutable.with(ints);
List<Integer> list = intList.collect(Integer::valueOf);

如果你想要最后的盒装集合,这就是collectIntArrayList的代码在幕后做的事情:

public <V> MutableList<V> collect(IntToObjectFunction<? extends V> function)
{
    return this.collect(function, FastList.newList(this.size));
}

public <V, R extends Collection<V>> R collect(IntToObjectFunction<? extends V> function, 
                                              R target)
{
    for (int i = 0; i < this.size; i++)
    {
        target.add(function.valueOf(this.items[i]));
    }
    return target;
}

由于这个问题是关于性能的,所以我使用你的解决方案编写了一些JMH基准测试,这是最受欢迎的答案以及Eclipse Collections的原始和盒装版本。

import org.eclipse.collections.api.list.primitive.IntList;
import org.eclipse.collections.impl.factory.primitive.IntLists;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@State(Scope.Thread)
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
@Fork(2)
public class IntegerArrayListFromIntArray
{
    private int[] source = IntStream.range(0, 1000).toArray();

    public static void main(String[] args) throws RunnerException
    {
        Options options = new OptionsBuilder().include(
                ".*" + IntegerArrayListFromIntArray.class.getSimpleName() + ".*")
                .forks(2)
                .mode(Mode.Throughput)
                .timeUnit(TimeUnit.SECONDS)
                .build();
        new Runner(options).run();
    }

    @Benchmark
    public List<Integer> jdkClassic()
    {
        List<Integer> list = new ArrayList<>(source.length);
        for (int each : source)
        {
            list.add(each);
        }
        return list;
    }

    @Benchmark
    public List<Integer> jdkStreams1()
    {
        List<Integer> list = new ArrayList<>(source.length);
        Collections.addAll(list,
                Arrays.stream(source).boxed().toArray(Integer[]::new));
        return list;
    }

    @Benchmark
    public List<Integer> jdkStreams2()
    {
        return Arrays.stream(source).boxed().collect(Collectors.toList());
    }

    @Benchmark
    public IntList ecPrimitive()
    {
        return IntLists.immutable.with(source);
    }

    @Benchmark
    public List<Integer> ecBoxed()
    {
        return IntLists.mutable.with(source).collect(Integer::valueOf);
    }
}

这些是我的Mac Book Pro上的这些测试的结果。单位是每秒的操作数,因此数字越大越好。我使用ImmutableIntList作为ecPrimitive基准,因为Eclipse Collections中的MutableIntList默认情况下不会复制数组。它只是适应你给它的数组。这报告了ecPrimitive的更大数字,误差幅度非常大,因为它实质上是衡量单个对象创建的成本。

# Run complete. Total time: 00:06:52

Benchmark                                  Mode  Cnt        Score      Error  Units
IntegerArrayListFromIntArray.ecBoxed      thrpt   40   191671.859 ± 2107.723  ops/s
IntegerArrayListFromIntArray.ecPrimitive  thrpt   40  2311575.358 ± 9194.262  ops/s
IntegerArrayListFromIntArray.jdkClassic   thrpt   40   138231.703 ± 1817.613  ops/s
IntegerArrayListFromIntArray.jdkStreams1  thrpt   40    87421.892 ± 1425.735  ops/s
IntegerArrayListFromIntArray.jdkStreams2  thrpt   40   103034.520 ± 1669.947  ops/s

如果有人发现基准测试的任何问题,我会很乐意进行更正并再次运行它们。

注意:我是Eclipse Collections的提交者。

答案 5 :(得分:0)

Arrays.stream(ints).forEach(list::add);

这基本上用2(使用Java 8)执行1(在数组上迭代)。 (其中1和2代表您的原始问题)

答案 6 :(得分:0)

其中stateb是列表'' 存储桶是二维数组

statesb = IntStream.of(bucket [j-1])。boxed()。collect(Collectors.toList());

导入java.util.stream.IntStream;

请参阅https://examples.javacodegeeks.com/core-java/java8-convert-array-list-example/

答案 7 :(得分:0)

第一种方法更好,第二种方法花费更多时间创建新数组并转换为列表

答案 8 :(得分:-3)

老路但仍在工作!

 int[] values = {1,2,3,4};
 List<Integer> list = new ArrayList<>(values.length);

 for(int valor : values) {
     list.add(valor);
 }