Как преобразовать список в int[] в Java?
это похоже на этот вопрос:
как конвертировать int[] в Integer[] в Java?
Я новичок в Java. Как я могу преобразовать List<Integer> to int[] в Java? Я в замешательстве, потому что List.toArray() на самом деле возвращает Object[], который может быть брошен в преисподнюю Integer[] или int[].
прямо сейчас я использую цикл, чтобы сделать это:
int[] toIntArray(List<Integer> list){
int[] ret = new int[list.size()];
for(int i = 0;i < ret.length;i++)
ret[i] = list.get(i);
return ret;
}
Я уверен, что есть лучший способ сделать это.
17 ответов:
к сожалению, я не верю, что там действительно и лучший способ сделать это из-за характера обработки Java примитивных типов, бокса, массивов и дженериков. В частности:
List<T>.toArrayне будет работать, потому что нет никакого преобразования изIntegertoint- вы не можете использовать
intв качестве аргумента типа для дженериков, так что это будет есть бытьint- конкретный метод (или тот, который использовал отражение, чтобы сделать неприятный обман.)Я считаю, что есть библиотеки, которые автоматически версиях такой способ для всех примитивных типов (т. е. есть шаблон, который копируется для каждого типа). Это некрасиво, но так оно и есть, я боюсь : (
даже если
Arraysкласс вышел до того, как дженерики прибыли в Java, он все равно должен был бы включать все ужасные перегрузки, если бы он был введен сегодня (предполагая, что вы хотите использовать примитив матрицы.)
еще никто не упоминал потоки, добавленные в Java 8, так что вот оно:
int[] array = list.stream().mapToInt(i->i).toArray();
мысли:
- простой
Stream#toArrayвозвращаетObject[], Так что это не то, что мы хотим. ТакжеStream#toArray(IntFunction<A[]> generator)не делает то, что мы хотим, потому что общий типAне может представлять примитивint- поэтому было бы неплохо иметь некоторый поток, который мог бы обрабатывать примитивный тип
int, потому чтоtoArrayметод, скорее всего, также вернетint[]массив (возвращая что-то еще вродеObject[]или даже в штучной упаковкеInteger[]было бы противоестественно, здесь). И к счастью Java 8 имеет такой поток:IntStreamтак что теперь единственное, что нам нужно выяснить, это как преобразовать наш
Stream<Integer>(который будет возвращен изlist.stream()) к этому блестящемуIntStream. ЗдесьmapToIntметод приходит на помощь. Все, что нам нужно сделать, это предоставить некоторое отображение изIntegerдоint. Мы могли бы использовать что-то вродеInteger#getValueкоторый возвращаетint:
mapToInt( (Integer i) -> i.intValue())(или если кто-то предпочитает
mapToInt(Integer::intValue))но подобный код может быть сгенерирован с помощью распаковки, так как компилятор знает, что результат этой лямбды должен быть
int(Lambda вmapToIntвнедрениеToIntFunctionинтерфейс, который ожидает тело дляint applyAsInt(T value)метод, который, как ожидается, вернетint).так что мы можем просто написать
mapToInt((Integer i)->i)или проще (так как
Integer iтип может быть выведено компилятором, потому чтоList<Integer>#stream()возвращаетStream<Integer>)
mapToInt(i -> i)
в дополнение к Commons Lang, вы можете сделать это с гуавы ' s метод
Ints.toArray(Collection<Integer> collection):List<Integer> list = ... int[] ints = Ints.toArray(list);это избавляет вас от необходимости выполнять промежуточное преобразование массива, которое требуется для эквивалента Commons Lang.
самый простой способ сделать это-использовать Apache Commons Lang. Он имеет удобный класс ArrayUtils, который может делать то, что вы хотите. Используйте
toPrimitiveметод с перегрузкой для массиваIntegers.List<Integer> myList; ... assign and fill the list int[] intArray = ArrayUtils.toPrimitive(myList.toArray(new Integer[myList.size()]));таким образом, вы не изобретаете велосипед. У Commons Lang есть очень много полезных вещей, которые Java пропустил. Выше я решил создать целочисленный список нужного размера. Вы также можете использовать статический целочисленный массив 0-длины и позволить Java выделить массив нужного размера:
static final Integer[] NO_INTS = new Integer[0]; .... int[] intArray2 = ArrayUtils.toPrimitive(myList.toArray(NO_INTS));
int[] toIntArray(List<Integer> list) { int[] ret = new int[list.size()]; int i = 0; for (Integer e : list) ret[i++] = e; return ret; }небольшое изменение кода, чтобы избежать дорогостоящего индексирования списка (поскольку список не обязательно является ArrayList, но может быть связанным списком, для которого случайный доступ дорог)
Java 8 дал нам простой способ сделать это с помощью потоков...
использование коллекций
stream()функция, а затем сопоставление с ints, вы получите IntStream. С помощьюIntStreamмы можем вызвать toArray () который дает намint []int [] ints = list.stream().mapToInt(Integer::intValue).toArray();
здесь Java 8 однострочный код для этого
public int[] toIntArray(List<Integer> intList){ return intList.stream().mapToInt(Integer::intValue).toArray(); }
Я брошу еще один здесь. Я заметил несколько применений для петель, но вам даже не нужно ничего внутри цикла. Я упоминаю об этом только потому, что исходный вопрос пытался найти менее подробный код.
int[] toArray(List<Integer> list) { int[] ret = new int[ list.size() ]; int i = 0; for( Iterator<Integer> it = list.iterator(); it.hasNext(); ret[i++] = it.next() ); return ret; }Если Java разрешила несколько объявлений в цикле for, как это делает C++, мы могли бы пойти еще дальше и сделать for(int i = 0, Iterator it...
в конце концов, хотя (эта часть только мое мнение), если вы собираетесь иметь функцию помощи или метод чтобы сделать что-то для вас, просто установите его и забудьте об этом. Это может быть один лайнер или десять; если вы никогда не будете смотреть на него снова, вы не будете знать разницы.
этот простой цикл всегда правильный! нет ошибок
int[] integers = new int[myList.size()]; for (int i = 0; i < integers.length; i++) { integers[i] = myList.get(i); }
если вы просто сопоставление
Integerдоintзатем вы должны рассмотреть используя параллелизм, так как ваша логика отображения не зависит от каких-либо переменных за пределами своей области.int[] arr = list.parallelStream().mapToInt(Integer::intValue).toArray();просто знайте об этом
обратите внимание, что параллелизм не является автоматически быстрее, чем выполнение операций последовательно, хотя это может быть, если у вас есть достаточно данных и процессорных ядер. В то время как агрегатные операции позволяют более легко реализовать параллелизм, это все еще ваша ответственность, чтобы определить, если ваше приложение подходит для параллелизма.
существует два способа отображения целых чисел в их примитивную форму:
через a
ToIntFunction.mapToInt(Integer::intValue)через явные анбоксинг С лямбда-выражение.
mapToInt(i -> i.intValue())через неявную (авто-) распаковку с лямбда выражение.
mapToInt(i -> i)
учитывая список с
nullстоимостьюList<Integer> list = Arrays.asList(1, 2, null, 4, 5);вот три варианта обработки
null:
- на
nullзначения перед отображением.int[] arr = list.parallelStream().filter(Objects::nonNull).mapToInt(Integer::intValue).toArray();карта
nullзначения по умолчанию.int[] arr = list.parallelStream().map(i -> i == null ? -1 : i).mapToInt(Integer::intValue).toArray();дескриптор
nullвнутри лямбда-выражения.int[] arr = list.parallelStream().mapToInt(i -> i == null ? -1 : i.intValue()).toArray();
int[] ret = new int[list.size()]; Iterator<Integer> iter = list.iterator(); for (int i=0; iter.hasNext(); i++) { ret[i] = iter.next(); } return ret;
на самом деле нет способа "однострочного" того, что вы пытаетесь сделать, потому что toArray возвращает объект [], и вы не можете бросить из объекта[] в int[] или Integer[] в int[]
попробуйте доллар (Регистрация этой редакции):
import static com.humaorie.dollar.Dollar.* ... List<Integer> source = ...; int[] ints = $(source).convert().toIntArray();
С Коллекции Eclipse, вы можете сделать следующее, Если у вас есть список типа
java.util.List<Integer>:List<Integer> integers = Lists.mutable.with(1, 2, 3, 4, 5); int[] ints = LazyIterate.adapt(integers).collectInt(i -> i).toArray(); Assert.assertArrayEquals(new int[]{1, 2, 3, 4, 5}, ints);если у вас уже есть тип коллекций Eclipse, например
MutableList, вы можете сделать следующее:MutableList<Integer> integers = Lists.mutable.with(1, 2, 3, 4, 5); int[] ints = integers.asLazy().collectInt(i -> i).toArray(); Assert.assertArrayEquals(new int[]{1, 2, 3, 4, 5}, ints);Примечание: я коммиттер для коллекций Eclipse
начиная с java 8 это может быть легко достигнуто с помощью
Stream APIint[] temp = list.stream().mapToInt(Integer::intValue).toArray();Если вы хотите получить дополнительную информацию о том, как этот процесс завершен id хотел бы перенаправить вас по этой ссылке http://www.techiedelight.com/convert-stream-array-java/#2
Я бы рекомендовал вам использовать
List<?>скелетная реализация из API коллекций java, похоже, очень полезна в этом конкретном случае:package mypackage; import java.util.AbstractList; import java.util.Arrays; import java.util.Collections; import java.util.List; public class Test { //Helper method to convert int arrays into Lists static List<Integer> intArrayAsList(final int[] a) { if(a == null) throw new NullPointerException(); return new AbstractList<Integer>() { @Override public Integer get(int i) { return a[i];//autoboxing } @Override public Integer set(int i, Integer val) { final int old = a[i]; a[i] = val;//auto-unboxing return old;//autoboxing } @Override public int size() { return a.length; } }; } public static void main(final String[] args) { int[] a = {1, 2, 3, 4, 5}; Collections.reverse(intArrayAsList(a)); System.out.println(Arrays.toString(a)); } }остерегайтесь бокса / распаковки недостатков
используя лямбду, вы можете сделать это (компилируется в jdk lambda):
public static void main(String ars[]) { TransformService transformService = (inputs) -> { int[] ints = new int[inputs.size()]; int i = 0; for (Integer element : inputs) { ints[ i++ ] = element; } return ints; }; List<Integer> inputs = new ArrayList<Integer>(5) { {add(10); add(10);} }; int[] results = transformService.transform(inputs); } public interface TransformService { int[] transform(List<Integer> inputs); }
Comments