English 中文(简体)
原始的多头的数组转换成多头的列表
原标题:
  • 时间:2009-04-16 00:19:41
  •  标签:

这可能有点简单,headdesk有点问题,但我的第一次尝试出人意料的完全失败。我想把数组的原始渴望,把它变成一个列表,我试图这样做:

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

什么正确的方法吗?

最佳回答

我发现它方便使用apache commons lang ArrayUtils (< a href = " http://commons.apache.org/proper/commons lang/javadocs/api - 3.1 / - org/apache/commons/lang3/arrayutils.html # toObject(长[])”rel = " noreferrer " > JavaDoc < / >、< a href = " https://mvnrepository.com/artifact/org.apache.commons/commons-lang3/latest " rel = " noreferrer " > Maven依赖< / >)

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

<强>编辑:< /强>更新提供一个完整的转换列表所显示的评论和其他修复。

问题回答

因为Java 8现在可以使用流:

long[] arr = { 1, 2, 3, 4 };
List<Long> list = Arrays.stream(arr).boxed().collect(Collectors.toList());
import java.util.Arrays;
import org.apache.commons.lang.ArrayUtils;

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

754324年< a href = " https://stackoverflow.com/questions/754294/convert-an-array-of-primitive-longs-into-a-list-of-longs/754324 " > hallidave < / >和< a href = " https://stackoverflow.com/questions/754294/convert-an-array-of-primitive-longs-into-a-list-of-longs/754325 # 754325 " > jpalecek < / >有权idea-iterating一array-but他们不利用提供的一个功能<代码> ArrayList < /代码>:< em >以来列表的大小是已知的< / em >在这种情况下,你应该指定它当您创建<代码> ArrayList > < /代码。

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

这种方式,没有不必要的数组创建只有被丢弃的<代码> ArrayList > < /代码,因为他们是太短,也没有空的“槽”被浪费,因为<代码> ArrayList < /代码>高估了它的空间需求。当然,如果你继续将元素添加到列表中,需要一个新的支持数组。

更详细的,但是这个工作原理:

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

在你看来arrays . aslist()例子解释输入列表长[]数组而不是多头的列表。有点奇怪,肯定的。自动装箱根本t工作在这种情况下,你想要的方式。

另一种可能性,< a href = " https://github.com/google/guava " rel = " noreferrer " > < / >的番石榴库提供了这是< a href = " http://google.github.io/guava/releases/snapshot/api/docs/com/google/common/primitives/Longs.html asList-long……——“rel = " noreferrer " > <代码> Longs.asList() < /代码> < / >,与其他类似的实用程序类的原始类型。

import com.google.common.primitives.Longs;

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

<一口>问题被问及如何将数组转化为一个列表。到目前为止大多数答案显示如何创建一个新的< em > < / em >与数组相同的内容列表,或称为第三方库。然而,有简单,内置选项这样的转换。他们中的一些已经勾勒出在其他答案(例如< a href = " https://stackoverflow.com/a/17983559/3182664 " >这一个< / >)。但我想指出,精心实施一定的自由度,显示了潜在的好处,缺点和警告。< /一口>

至少有两个重要的区别:

  • Whether the resulting list should be a view on the array or whether it should be a new list
  • Whether the resulting list should be modifiable or not

迅速的选项将在这里总结,一个完整的示例程序这个答案的底部所示。


<强>创建一个新的列表和创建一个< em > < / em >视图数组< /强>

当结果应该是一个新<强> < /强>列表,然后从其他答案的方法可能是使用:

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

但是应该考虑这样做的缺点:数组与1000000 <代码> < /代码>长值将占据大约8 mb的内存。新列表将< em > < / em >占领大约8 mb。当然,必须遍历整个数组在创建该列表。在许多情况下,创建一个新的列表是没有必要的。相反,它足以创建一个<强>视图< /强>数组:

// 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 > < /代码方法)< /一口>

的含义有一个< em > < / em >视图的数组,数组列表中可见的变化:

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

现在,这是一个真实的副本,相当于什么是与上面所示的基于流的解决方案来实现。


<强>创建一个< em >修改< / em >视图或一个< em >的< /强> < / em >视图

在许多情况下,这将是足够的,当列表是< em >只读< / em >。结果列表的内容往往会不被修改,但只传递给下游加工,只有读取列表。

允许列表的修改提出了一些问题:

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?

可以创建一个数组,列表视图是< em >修改< / em >。这意味着更改列表中,如设置一个新值在一定的指数,将数组中可见。

但它是不可能创建一个列表视图,< em >结构修改< / em >。这意味着它是不可能做的操作影响< em > < / em >列表的大小。这完全是因为潜在的大小< em > < / em >数组不能被改变。


下面是一个< a href = " https://stackoverflow.com/help/mcve " > 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

不,没有自动转换原语类型数组的数组的盒装引用类型。你只能做

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

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

另一种方式使用Java 8。

long[] input = someAPI.getSomeLongs();
LongStream.of(input).boxed().collect(Collectors.toList()));

我对这些问题:编写一个小型图书馆

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

在你检查< a href = " https://bitbucket.org/adamldavis/dollar/wiki/Home " rel = " nofollow noreferrer " > < / >。

另一个< a href = " https://stackoverflow.com/a/30636289/330457 " > < / >与Java 8。

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

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

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

如果你想要类似的语义<代码>数组。asList > < /代码然后你需要编写(或使用别人s)客户实施<代码> < /代码>列表(可能通过<代码> AbstractList > < /代码。它应该实现与<代码>数组。asList > < /代码,只值进行装箱和拆箱。

您可以使用< a href = " http://transmorph.sourceforge.net " rel = " nofollow noreferrer " > transmorph < / >:

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

它同样适用如果来源是一个整数数组为例。

我知道这个问题是年龄,但是……您还可以编写您自己的转换方法:

@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]);
        f或 (int i = 0; i < length; i++) {
            Object element = Array.get(items[0], i);
            T item = (T)element;
            list.add(item);
        }
    } else {
        f或 (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);

虽然有可能创建一个新的列表,添加所有的值(通过for循环或流),我真的一直在努力大数组和表现不佳。所以我创建我自己的易于使用的原始数组包装类。

例子:

long[] arr = new long[] {1,2,3};
PrimativeList<Long> list = PrimativeList.create(arr); // detects long[] and returns PrimativeList<Long>

System.out.println(list.get(1)); // prints: 2
list.set(2, 15);
System.out.println(arr[2]);  // prints: 15

Get it here: https://github.com/Sf298/Sauds-Toolbox/blob/master/src/main/java/PrimitiveArrayWrapper/PrimitiveList.java

注意:我还没完全测试,所以请让我知道如果你发现任何错误/问题。

您可以使用<代码> LongStream > < /代码

List<Long> longs = LongStream.of(new long[]{1L, 2L, 3L}).boxed()
                             .collect(Collectors.toList());




相关问题
热门标签