代码之家  ›  专栏  ›  技术社区  ›  Brandon Yarbrough

将原始long数组转换为long列表

  •  149
  • Brandon Yarbrough  · 技术社区  · 16 年前

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

    做这件事的正确方法是什么?

    17 回复  |  直到 10 年前
        1
  •  101
  •   Eran Medan    7 年前

    从Java 8开始,您现在可以使用流来实现这一点:

    long[] arr = { 1, 2, 3, 4 };
    List<Long> list = Arrays.stream(arr).boxed().collect(Collectors.toList());
    
        2
  •  91
  •   marcinj    11 年前

    我发现使用apache commons lang ArrayUtils很方便( JavaDoc , Maven dependency

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

    它也有相反的API

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

    编辑: 已更新,以提供注释和其他修复建议的完整列表转换。

        3
  •  38
  •   Marco Pelegrini    15 年前
    import java.util.Arrays;
    import org.apache.commons.lang.ArrayUtils;
    
    List<Long> longs = Arrays.asList(ArrayUtils.toObject(new long[] {1,2,3,4}));
    
        4
  •  29
  •   Community CDub    8 年前

    hallidave jpalecek 有正确的想法——迭代数组——但他们没有利用 ArrayList :因为 在这种情况下,您应该在创建时指定它 数组列表 .

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

    这样,就不会创建不必要的数组,只会被丢弃 数组列表 因为它们太短了,没有空的“插槽”被浪费,因为 数组列表 高估了其空间需求。当然,如果继续向列表中添加元素,则需要一个新的支持数组。

        5
  •  17
  •   hallidave    16 年前

    有点冗长,但这是有效的:

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

    在您的示例中,Arrays.asList()似乎将输入解释为长[]数组列表,而不是长数组列表。当然,这有点令人惊讶。在这种情况下,自动拳击并没有按照你想要的方式发挥作用。

        6
  •  17
  •   Pang Ajmal PraveeN    7 年前

    作为另一种可能性, the Guava library Longs.asList() ,其他基本类型也有类似的实用程序类。

    import com.google.common.primitives.Longs;
    
    long[] input = someAPI.getSomeLongs();
    List<Long> output = Longs.asList(input);
    
        7
  •  7
  •   jpalecek    16 年前

    与数组内容相同的列表,或引用第三方库。然而,这种转换有简单的内置选项。其中一些已经在其他答案中进行了概述(例如。 this one ).但我想指出并阐述这里实施的某些自由度,并展示潜在的好处、缺点和注意事项。

    • 结果列表是否应该是 视图 在数组上,或者它是否应该是 列表
    • 结果列表是否应 或不

    这里将快速总结这些选项,完整的示例程序显示在这个答案的底部。


    创建新列表与创建 视图 在阵列上

    当结果应该是

    List<Long> list = Arrays.stream(array).boxed().collect(Collectors.toList());
    

    但人们应该考虑这样做的缺点:一个有1000000的数组 long 值将占用大约8MB的内存。新名单将 大约占用8兆字节。当然,在创建此列表时必须遍历整个数组。在许多情况下,创建新列表根本不是必需的。相反,只需创建一个 视图

    // This occupies ca. 8 MB
    long array[] = { /* 1 million elements */ }
    
    // Properly implemented, this list will only occupy a few bytes,
    // and the array does NOT have to be traversed, meaning that this
    // operation has nearly ZERO memory- and processing overhead:
    List<Long> list = asList(array);
    

    (请参阅底部的示例,了解 toList 方法)

    视图 数组中的变化将在列表中可见:

    long array[] = { 12, 34, 56, 78 };
    List<Long> list = asList(array);
    
    System.out.println(list.get(1)); // This will print 34
    
    // Modify the array contents:
    array[1] = 12345;
    
    System.out.println(list.get(1)); // This will now print 12345!
    

    幸运的是,创建一个副本(即 不受数组修改影响的列表)从视图中删除是微不足道的:

    List<Long> copy = new ArrayList<Long>(asList(array));
    


    创建一个 不可修改的 视图

    在许多情况下,当列表满足以下条件时就足够了 结果列表的内容通常不会被修改,而只会传递给仅读取列表的下游处理。

    允许对列表进行修改会引发一些问题:

    long array[] = { 12, 34, 56, 78 };
    List<Long> list = asList(array);
    
    list.set(2, 34567);           // Should this be possible?
    System.out.println(array[2]); // Should this print 34567?
    list.set(3, null);            // What should happen here?
    list.add(99999);              // Should this be possible?
    

    这意味着列表中的更改,例如在某个索引处设置新值,将在数组中可见。

    但是,不可能创建以下列表视图 结构可修改 这意味着不可能进行影响 尺寸 数组 无法更改。


    以下是一个 MCVE

    import java.util.AbstractList;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Objects;
    import java.util.RandomAccess;
    
    public class PrimitiveArraysAsLists
    {
        public static void main(String[] args)
        {
            long array[] = { 12, 34, 56, 78 };
    
            // Create VIEWS on the given array
            List<Long> list = asList(array);
            List<Long> unmodifiableList = asUnmodifiableList(array);
    
            // If a NEW list is desired (and not a VIEW on the array), this
            // can be created as well:
            List<Long> copy = new ArrayList<Long>(asList(array));
    
            System.out.println("array           : " + Arrays.toString(array));
            System.out.println("list            : " + list);
            System.out.println("unmodifiableList: " + unmodifiableList);
            System.out.println("copy            : " + copy);        
    
            // Modify a value in the array. The changes will be visible
            // in the list and the unmodifiable list, but not in
            // the copy.
            System.out.println("Changing value at index 1 of the array...");
            array[1] = 34567;
    
            System.out.println("array           : " + Arrays.toString(array));
            System.out.println("list            : " + list);
            System.out.println("unmodifiableList: " + unmodifiableList);
            System.out.println("copy            : " + copy);        
    
            // Modify a value of the list. The changes will be visible
            // in the array and the unmodifiable list, but not in
            // the copy.
            System.out.println("Changing value at index 2 of the list...");
            list.set(2, 56789L);
    
            System.out.println("array           : " + Arrays.toString(array));
            System.out.println("list            : " + list);
            System.out.println("unmodifiableList: " + unmodifiableList);
            System.out.println("copy            : " + copy);        
    
    
            // Certain operations are not supported:
            try
            {
                // Throws an UnsupportedOperationException: This list is 
                // unmodifiable, because the "set" method is not implemented
                unmodifiableList.set(2, 23456L);
            }
            catch (UnsupportedOperationException e) 
            {
                System.out.println("Expected: " + e);
            }
    
            try
            {
                // Throws an UnsupportedOperationException: The size of the
                // backing array cannot be changed
                list.add(90L);
            }
            catch (UnsupportedOperationException e) 
            {
                System.out.println("Expected: " + e);
            }
    
    
            try
            {
                // Throws a NullPointerException: The value 'null' cannot be  
                // converted to a primitive 'long' value for the underlying array
                list.set(2, null);
            }
            catch (NullPointerException e)
            {
                System.out.println("Expected: " + e);
            }
    
        }
    
        /**
         * Returns an unmodifiable view on the given array, as a list.
         * Changes in the given array will be visible in the returned
         * list.
         *  
         * @param array The array
         * @return The list view
         */
        private static List<Long> asUnmodifiableList(long array[])
        {
            Objects.requireNonNull(array);
            class ResultList extends AbstractList<Long> implements RandomAccess
            {
                @Override
                public Long get(int index)
                {
                    return array[index];
                }
    
                @Override
                public int size()
                {
                    return array.length;
                }
            };
            return new ResultList();
        }
    
        /**
         * Returns a view on the given array, as a list. Changes in the given 
         * array will be visible in the returned list, and vice versa. The
         * list does not allow for <i>structural modifications</i>, meaning
         * that it is not possible to change the size of the list.
         *  
         * @param array The array
         * @return The list view
         */
        private static List<Long> asList(long array[])
        {
            Objects.requireNonNull(array);
            class ResultList extends AbstractList<Long> implements RandomAccess
            {
                @Override
                public Long get(int index)
                {
                    return array[index];
                }
    
                @Override
                public Long set(int index, Long element)
                {
                    long old = array[index];
                    array[index] = element;
                    return old;
                }
    
                @Override
                public int size()
                {
                    return array.length;
                }
            };
            return new ResultList();
        }
    
    }
    

    array           : [12, 34, 56, 78]
    list            : [12, 34, 56, 78]
    unmodifiableList: [12, 34, 56, 78]
    copy            : [12, 34, 56, 78]
    Changing value at index 1 of the array...
    array           : [12, 34567, 56, 78]
    list            : [12, 34567, 56, 78]
    unmodifiableList: [12, 34567, 56, 78]
    copy            : [12, 34, 56, 78]
    Changing value at index 2 of the list...
    array           : [12, 34567, 56789, 78]
    list            : [12, 34567, 56789, 78]
    unmodifiableList: [12, 34567, 56789, 78]
    copy            : [12, 34, 56, 78]
    Expected: java.lang.UnsupportedOperationException
    Expected: java.lang.UnsupportedOperationException
    Expected: java.lang.NullPointerException
    
        8
  •  5
  •   dfa    15 年前

    不,基本类型的数组不会自动转换为其盒装引用类型的数组。你只能这么做

    long[] input = someAPI.getSomeLongs();
    List<Long> lst = new ArrayList<Long>();
    
    for(long l : input) lst.add(l);
    
        9
  •  4
  •   ravenskater    9 年前

    Java 8的另一种方式。

    long[] input = someAPI.getSomeLongs();
    LongStream.of(input).boxed().collect(Collectors.toList()));
    
        10
  •  3
  •   Duncan McGregor Evgeniy Dorofeev    12 年前

    我正在为这些问题编写一个小型库:

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

    如果你介意的话,检查一下 here .

        11
  •  3
  •   Community CDub    8 年前

    way Java 8。

    final long[] a = new long[]{1L, 2L};
    final List<Long> l = Arrays.stream(a).boxed().collect(Collectors.toList());
    
        12
  •  3
  •   Marco13    6 年前

    结合帕维尔和汤姆的答案,我们得到这个

       @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);
                }
            };
        }
    
        13
  •  2
  •   Tom Hawtin - tackline    16 年前

    如果你想要类似的语义 Arrays.asList 然后,您需要编写(或使用其他人的)客户实现 List (可能通过 AbstractList 。它的实施方式应该与 Arrays.asList ,只有box和unbox值。

        14
  •  2
  •   cchabanois    15 年前

    您可以使用 transmorph :

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

    例如,如果源是一个整数数组,它也可以工作。

        15
  •  2
  •   Pavel Netesa    12 年前

    我知道这个问题已经够老了,但是。..你也可以编写自己的转换方法:

    @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);