2009-04-16 3 views
105

Это может быть немного простой вопрос с гарнитурой, но моя первая попытка на удивление полностью не сработала. Я хотел взять массив примитивных долгот и превратить его в список, который я пытался сделать так:Преобразование массива примитивных длин в список длин.

long[] input = someAPI.getSomeLongs(); 
List<Long> inputAsList = Arrays.asList(input); //Total failure to even compile! 

Что правильный способ сделать это?

+5

Я думаю, что мы имели один и тот же вопрос для Интс, не так ли? –

+1

@ Тома, да: http://stackoverflow.com/questions/1467913/arrays-aslist-not-working-as-it-should – finnw

ответ

94

Я нашел, что это удобно делать с помощью Apache Commons Lang ArrayUtils (JavaDoc)

long[] input = someAPI.getSomeLongs(); 
Long[] inputBoxed = ArrayUtils.toObject(input); 
List<Long> inputAsList = Arrays.asList(inputBoxed); 

также имеет обратный API

long[] backToPrimitive = ArrayUtils.toPrimitive(objectArray); 

EDIT: обновляется, чтобы обеспечить полное превращение в список, предложенный комментариями и другими исправлениями.

+3

Учитывая, что это создает _array_ Longs, _not List_, он не отвечает на вопрос OP и получает мой downvote. Как, черт возьми, это получило 56 побед и желанный «чек» ??? – user949300

+6

Потому что люди могут легко сделать 'Arrays.asList (ArrayUtils.toObject (input))' вероятно. –

+0

Я согласен с @ user949300. Это не отвечает на вопрос. – ovaherenow

16

немного более многословным, но это работает:

List<Long> list = new ArrayList<Long>(); 
    for (long value : input) { 
     list.add(value); 
    } 

В вашем примере оказывается, что Arrays.asList() интерпретирует ввод как список длинных [] массивы вместо списка Longs. Немного удивительно, конечно. Автобоксинг просто не работает так, как вы хотите, в этом случае.

7

Нет, автоматическое преобразование из массива примитивного типа в массив их ссылочных типов в боксе отсутствует. Вы можете сделать это только

long[] input = someAPI.getSomeLongs(); 
List<Long> lst = new ArrayList<Long>(); 

for(long l : input) lst.add(l); 
2

Если вы хотите аналогичную семантику Arrays.asList, то вам нужно написать (или использовать чужое) осуществление клиента в List (возможно через AbstractList. Он должен иметь много ту же реализацию, как Arrays.asList, . только коробка и распаковывать значения

29

hallidave и jpalecek имеют правильное представление — итерация массива — но они не воспользоваться функцией, предоставленной ArrayList: поскольку размер списка известно, в этом случае вы должны указать его при создании ArrayList.

List<Long> list = new ArrayList<Long>(input.length); 
for (long n : input) 
    list.add(n); 

Таким образом, нет ненужных массивов создаются только, чтобы быть отброшены ArrayList, потому что они оказываются слишком короткие, и нет пустых «слотов» не потрачены впустую, поскольку ArrayList переоценила свои потребности в пространстве. Конечно, если вы продолжаете добавлять элементы в список, вам понадобится новый массив поддержки.

+0

Я, как правило, не учитываю спецификацию длины, если этот код не является частью высокая производительность или массив, как ожидается, будет чрезвычайно большим. Я думаю, что отказ от длины делает код немного читабельнее. – hallidave

2

Вы можете использовать transmorph:

Transmorph transmorph = new Transmorph(new DefaultConverters()); 
List<Long> = transmorph.convert(new long[] {1,2,3,4}, new TypeReference<List<Long>>() {}); 

Он также работает, если источником является массивом целых чисел, например.

4

Я пишу небольшую библиотеку для этих задач:

long[] input = someAPI.getSomeLongs(); 
List<Long> = $(input).toList(); 

В случае, если вы заботитесь проверить его here.

+0

хорошая библиотека! сначала я не был уверен, что это была Java ... Мне нравится стиль JQuery –

37
import java.util.Arrays; 
import org.apache.commons.lang.ArrayUtils; 

List<Long> longs = Arrays.asList(ArrayUtils.toObject(new long[] {1,2,3,4})); 
+2

Объяснение того, что это делает и будет ли это сторонняя библиотека, будет полезна. –

2

Я знаю, этот вопрос достаточно старый, но ... Вы также можете написать свой собственный метод преобразования:

@SuppressWarnings("unchecked") 
public static <T> List<T> toList(Object... items) { 

    List<T> list = new ArrayList<T>(); 

    if (items.length == 1 && items[0].getClass().isArray()) { 
     int length = Array.getLength(items[0]); 
     for (int i = 0; i < length; i++) { 
      Object element = Array.get(items[0], i); 
      T item = (T)element; 
      list.add(item); 
     } 
    } else { 
     for (Object i : items) { 
      T item = (T)i; 
      list.add(item); 
     } 
    } 

    return list; 
} 

После включить его с помощью статического импорта, возможные порядки могут быть:

long[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 
    List<Long> list = toList(array); 

или

List<Long> list = toList(1l, 2l, 3l, 4l, 5l, 6l, 7l, 8l, 9l); 
+0

относительно: 'catch (ArrayIndexOutOfBoundsException ex) {/ * Готовые элементы массива * /}', вы ужасный человек. –

+0

Эй, мужик, спасибо за это! Ваше ироничное замечание заставило меня найти лучшее решение - получить длину массива через Array.getLength(). –

+0

Фантастический! Я рад, что мое сардоническое отношение привело к прогрессу, а не к общим неприятным ощущениям вокруг. На самом деле не исключено использование исключений, за исключением необычных условий. Они удивительно дороги для создания.Эта новая версия намного, МНОГО быстрее. –

3

Объединение Павла и ответы Тома мы получаем это

@SuppressWarnings("unchecked") 
    public static <T> List<T> asList(final Object array) { 
     if (!array.getClass().isArray()) 
      throw new IllegalArgumentException("Not an array"); 
     return new AbstractList<T>() { 
      @Override 
      public T get(int index) { 
       return (T) Array.get(array, index); 
      } 

      @Override 
      public int size() { 
       return Array.getLength(array); 
      } 
     }; 
    } 
61

Поскольку Java 8 теперь вы можете использовать потоки для этого:

long[] arr = {1,2,3,4}; 
List<Long> list = Arrays.stream(arr).boxed().collect(Collectors.toList()); 
+2

Ницца! К сожалению, и несколько загадочно, функция 'stream' определена только для' int [] ',' long [] 'и' double [] '. – Norswap

+1

Кроме того, вы можете использовать 'LongStream.of (arr) .boxed() ...'. – aioobe

+1

'Arrays.stream (arr) .boxed(). Collect (Collectors.toList());' К сожалению, это может возвращать только 'List ' –

15

В качестве другой возможности the Guava library обеспечивает это как Longs.asList(), с аналогичными классами утилита для другие примитивные типы.

import com.google.common.primitives.Longs; 

long[] input = someAPI.getSomeLongs(); 
List<Long> output = Longs.asList(input); 
3

Другой way с Java 8.

final long[] a = new long[]{1L, 2L}; 
final List<Long> l = Arrays.stream(a).boxed().collect(Collectors.toList()); 
+1

При возврате списка (не назначая его) я обнаружил, что мне нужно было сделать: 'Arrays.stream (a) .boxed(). Collect (Collectors. toList());' – Jon

+0

Это идентично [этот существующий ответ ] (https://stackoverflow.com/a/23117638). – Pang

+0

@Pang Действительно ... –

4

Другой способ с Java 8.

long[] input = someAPI.getSomeLongs(); 
LongStream.of(input).boxed().collect(Collectors.toList())); 
Смежные вопросы