Преобразование массива в список
Чтобы преобразовать массив Integer в список integer, я пробовал следующие подходы:
-
Инициализировать список (тип Integer), перебрать массив и вставить в список
-
Используя Java 8 Streams:
int[] ints = {1, 2, 3};
List<Integer> list = new ArrayList<Integer>();
Collections.addAll(list, Arrays.stream(ints).boxed().toArray(Integer[]::new));
Что лучше с точки зрения производительности?
Ответы
Ответ 1
Второй создает новый массив целых чисел (первый проход), а затем добавляет все элементы этого нового массива в список (второй проход). Таким образом, он будет менее эффективным, чем первый, который делает один проход и не создает ненужный массив целых чисел.
Лучшим способом использования потоков будет
List<Integer> list = Arrays.stream(ints).boxed().collect(Collectors.toList());
который должен иметь примерно такую же производительность, как и первая.
Обратите внимание, что для такого небольшого массива существенной разницы не будет. Вы должны попытаться написать правильный, читаемый, поддерживаемый код, а не фокусироваться на производительности.
Ответ 2
Просто попробуйте что-нибудь вроде
Arrays.asList(array)
Ответ 3
Если вы не хотите изменять список:
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));
Ответ 4
Если вы имеете дело со строкой [] вместо int [], мы можем использовать
ArrayList<String> list = new ArrayList<>();
list.addAll(Arrays.asList(StringArray));
Ответ 5
Если вы не возражаете против сторонней зависимости, вы можете использовать библиотеку, которая изначально поддерживает коллекции примитивов, такие как Eclipse Collections, и вообще избегать упаковки. При необходимости вы также можете использовать примитивные коллекции для создания регулярных коллекций в штучной упаковке.
int[] ints = {1, 2, 3};
MutableIntList intList = IntLists.mutable.with(ints);
List<Integer> list = intList.collect(Integer::valueOf);
Если вы хотите получить упакованную коллекцию в конце, то, что делает код для collect
в IntArrayList
под прикрытием:
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
теста, потому что MutableIntList
в Eclipse, коллекции не копирует массив по умолчанию. Он просто адаптирует массив, который вы ему передаете. Это сообщало о еще больших числах для ecPrimitive
, с очень большим пределом погрешности, потому что это по существу 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.
Ответ 6
Arrays.stream(ints).forEach(list::add);
Это в основном делает 1 (итерация по массиву) с 2 (используя Java 8). (с 1 и 2 со ссылкой на ваш оригинальный вопрос)
Ответ 7
где stateb - это список. 'bucket - это двумерный массив.
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/
Ответ 8
Старый способ, но все еще работает!
int[] values = {1,2,3,4};
List<Integer> list = new ArrayList<>(values.length);
for(int valor : values) {
list.add(valor);
}