Как преобразовать List <Integer> в int [] в Java?
Это похоже на этот вопрос:
Как преобразовать int [] в Integer [] в Java?
Я новичок в Java. Как преобразовать List<Integer>
в int[]
в Java? Я запутался, потому что List.toArray()
фактически возвращает Object[]
, который может быть отброшен в nether 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;
}
Я уверен, что есть лучший способ сделать это.
Ответы
Ответ 1
К сожалению, я не верю, что действительно лучший способ сделать это из-за характера обработки Java примитивных типов, бокса, массивов и дженериков. В частности:
-
List<T>.toArray
не будет работать, потому что нет преобразования от Integer
до int
- Вы не можете использовать
int
как аргумент типа для дженериков, поэтому он должен был быть int
-специфическим методом (или тем, который использовал отражение, чтобы делать неприятные обманки).
Я считаю, что есть библиотеки, у которых есть автогенерированные версии этого типа метода для всех примитивных типов (т.е. есть шаблон, который копируется для каждого типа). Это уродливо, но так, как я боюсь: (
Несмотря на то, что класс Arrays
вышел до того, как дженерики прибыли на Java, все равно пришлось бы включать все ужасные перегрузки, если бы это было (предполагается, что вы хотите использовать примитивные массивы).
Ответ 2
Никто еще не упомянул потоки, добавленные в Java 8, так что вот так:
int[] array = list.stream().mapToInt(i->i).toArray();
Процесс мышления:
- simple
Stream#toArray
возвращает Object[]
, поэтому это не то, что мы хотим. Также Stream#toArray(IntFunction<A[]> generator)
не делает то, что мы хотим, потому что универсальный тип A
не может представлять примитив int
- поэтому было бы неплохо иметь некоторый поток, который мог бы обрабатывать примитивный тип
int
вместо оболочки Integer
, потому что его метод toArray
, скорее всего, также будет возвращать массив int[]
(возвращая что-то еще, например Object[]
или даже в штучной упаковке) Integer[]
было бы неестественно здесь). И, к счастью, в Java 8 есть такой поток, который IntStream
так что теперь единственное, что нам нужно выяснить, - это как преобразовать наш Stream<Integer>
(который будет возвращен из list.stream()
) в этот блестящий IntStream
. Здесь Stream#mapToInt(ToIntFunction<? super T> mapper)
метод приходит на помощь. Все, что нам нужно сделать, это перейти к отображению с Integer
на int
. Мы могли бы использовать что-то вроде Integer#getValue
, которое возвращает int
, например:
mapToInt( (Integer i) -> i.intValue() )
(или если кто-то предпочитает mapToInt(Integer::intValue)
)
но подобный код может быть сгенерирован с использованием распаковки, так как компилятор знает, что результатом этой лямбды должен быть int
(лямбда в mapToInt
- это реализация интерфейса ToIntFunction
, который ожидает тело для метода int applyAsInt(T value)
, который, как ожидается, вернет int
]).
Таким образом, мы можем просто написать
mapToInt((Integer i)->i)
Также, поскольку тип Integer
в (Integer i)
может быть выведен компилятором, поскольку List<Integer>#stream()
возвращает Stream<Integer>
, мы можем также пропустить его, что оставляет нас с
mapToInt(i -> i)
Ответ 3
В дополнение к Commons Lang вы можете сделать это с помощью Guava method Ints.toArray(Collection<Integer> collection)
:
List<Integer> list = ...
int[] ints = Ints.toArray(list);
Это избавляет вас от необходимости делать промежуточное преобразование массива, которое требует эквивалент Commons Lang.
Ответ 4
Самый простой способ сделать это - использовать Apache Commons Lang. У этого есть удобный класс ArrayUtils, который может делать то, что Вы хотите. Используйте метод toPrimitive
с перегрузкой для массива Integer
s.
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));
Ответ 5
Java 8 дала нам простой способ сделать это с помощью потоков...
Используя функцию collection stream()
, а затем сопоставляя ее с int, вы получите IntStream. С помощью IntStream
мы можем вызвать toArray(), который дает нам int []
int [] ints = list.stream().mapToInt(Integer::intValue).toArray();
к int []
в IntStream
Ответ 6
int[] toIntArray(List<Integer> list) {
int[] ret = new int[list.size()];
int i = 0;
for (Integer e : list)
ret[i++] = e;
return ret;
}
Незначительное изменение кода, чтобы избежать дорогостоящей индексации списка (поскольку список не обязательно является ArrayList, но может быть связанным списком, для которого случайный доступ дорог)
Ответ 7
Вот Java 8 однострочный код для этого
public int[] toIntArray(List<Integer> intList){
return intList.stream().mapToInt(Integer::intValue).toArray();
}
Ответ 8
Я брошу еще один здесь. Я заметил несколько применений для циклов, но вам даже не нужно ничего внутри цикла. Я упоминаю об этом только потому, что исходный вопрос пытался найти менее подробный код.
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, как это делает С++, мы могли бы сделать еще один шаг и сделать для (int я = 0, Iterator it...
В конце концов, хотя (эта часть - только мое мнение), если у вас будет функция помощи или метод, чтобы что-то сделать для вас, просто установите ее и забудьте об этом. Это может быть один лайнер или десять; если вы никогда не посмотрите на это снова, вы не узнаете разницу.
Ответ 9
Если вы просто сопоставляете Integer
с int
вам следует рассмотреть возможность использования параллелизма, поскольку ваша логика отображения не полагается на какие-либо переменные за пределами ее области.
int[] arr = list.parallelStream().mapToInt(Integer::intValue).toArray();
Просто знайте об этом
Обратите внимание, что параллелизм не выполняется автоматически быстрее, чем выполнение операций поочередно, хотя это может быть, если у вас достаточно данных и процессорных ядер. Хотя агрегированные операции позволяют вам более легко реализовать параллелизм, вы по-прежнему несете ответственность за определение того, подходит ли ваше приложение для параллелизма.
Существует два способа сопоставления целых чисел с их примитивной формой:
-
Через функцию ToIntFunction
.
mapToInt(Integer::intValue)
-
С помощью явного unboxing с выражением лямбда.
mapToInt(i -> i.intValue())
-
Через неявный (auto-) unboxing с выражением лямбда.
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();
Ответ 10
Этот простой цикл всегда правильный! нет ошибок
int[] integers = new int[myList.size()];
for (int i = 0; i < integers.length; i++) {
integers[i] = myList.get(i);
}
Ответ 11
Нет никакого способа "однострочного" того, что вы пытаетесь сделать, потому что toArray возвращает объект [], и вы не можете отбрасывать из Object [] в int [] или Integer [] в int []
Ответ 12
int[] ret = new int[list.size()];
Iterator<Integer> iter = list.iterator();
for (int i=0; iter.hasNext(); i++) {
ret[i] = iter.next();
}
return ret;
Ответ 13
попробуйте также Dollar (проверить эту версию):
import static com.humaorie.dollar.Dollar.*
...
List<Integer> source = ...;
int[] ints = $(source).convert().toIntArray();
Ответ 14
С Eclipse Collections вы можете сделать следующее, если у вас есть список типов 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 Collections, например 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
Ответ 15
Я бы порекомендовал вам использовать 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));
}
}
Остерегайтесь недостатков бокса/распаковки
Ответ 16
Используя лямбда, вы можете сделать это (компилируется в 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);
}
Ответ 17
@Override
public int findArray(int[] array, int[] subArray) {
Map<Integer, Integer> map = new LinkedHashMap();
int index = -1;
boolean flag = false;
for (int i = 0; i < subArray.length; i++) {
flag=false;
for (int j = 0; j < array.length; j++) {
if (subArray[i]==array[j]) {
map.put(subArray[i], j);
flag = true;
}
}
}
if (flag) {
Map.Entry<Integer, Integer> entry = map.entrySet().iterator().next();
index = entry.getValue();
}
return index;
}