143

これはちょっと簡単なヘッドデスクのような質問かもしれませんが、私の最初の試みは驚くべきことに完全にうまくいきませんでした。プリミティブ long の配列を取り、それをリストに変換したかったので、次のようにしようとしました。

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

これを行う正しい方法は何ですか?

4

17 に答える 17

123

Java 8 以降、そのためにストリームを使用できるようになりました。

long[] arr = { 1, 2, 3, 4 };
List<Long> list = Arrays.stream(arr).boxed().collect(Collectors.toList());
于 2014-04-16T18:41:11.430 に答える
36
import java.util.Arrays;
import org.apache.commons.lang.ArrayUtils;

List<Long> longs = Arrays.asList(ArrayUtils.toObject(new long[] {1,2,3,4}));
于 2010-06-02T18:32:43.253 に答える
35

Hallidavejpalecekは、配列を反復処理するという正しい考えを持っていますが、 によって提供される機能を利用してArrayListませArrayList

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

このようにして、不要な配列が作成され、ArrayList短すぎることが判明したために破棄されることはありませんArrayList。また、スペース要件を過大評価したために空の「スロット」が無駄になることもありません。もちろん、リストに要素を追加し続けると、新しいバッキング配列が必要になります。

于 2009-04-16T15:48:10.003 に答える
19

もう少し冗長ですが、これは機能します:

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

あなたの例では、Arrays.asList() が入力を Long のリストではなく long[] 配列のリストとして解釈しているようです。確かに、少し驚くべきことです。この場合、オートボクシングは思い通りに機能しません。

于 2009-04-16T00:28:44.567 に答える
18

別の可能性として、Guava ライブラリはこれを として提供しLongs.asList()、他のプリミティブ型に対して同様のユーティリティ クラスを提供します。

import com.google.common.primitives.Longs;

long[] input = someAPI.getSomeLongs();
List<Long> output = Longs.asList(input);
于 2015-08-04T23:05:10.730 に答える
7

いいえ、プリミティブ型の配列からボックス化された参照型の配列への自動変換はありません。あなただけができる

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

for(long l : input) lst.add(l);
于 2009-04-16T00:28:55.627 に答える
7

質問は、配列をリストに変換する方法について尋ねました。これまでのほとんどの回答は、配列と同じ内容の新しいリストを作成する方法、またはサードパーティのライブラリを参照する方法を示していました。ただし、この種の変換には簡単な組み込みオプションがあります。それらのいくつかは、他の回答ですでにスケッチされています(例:this one)。しかし、ここでは実装の自由度を指摘して詳しく説明し、潜在的な利点、欠点、および注意事項を示したいと思います。

少なくとも 2 つの重要な違いがあります。

  • 結果のリストが配列のビューであるべきか、それとも新しいリストであるべきか
  • 結果のリストを変更可能にするかどうか

ここでオプションを簡単に要約し、この回答の最後に完全なプログラム例を示します。


新しいリストの作成とアレイでのビューの作成

結果が新しいリストである必要がある場合は、他の回答からのアプローチのいずれかを使用できます。

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

ただし、これを行うことの欠点を考慮する必要があります。1000000long個の値を持つ配列は、約 8 メガバイトのメモリを占有します。新しいリスト約 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));

さて、これは真のコピーであり、上に示したストリームベースのソリューションで達成されるものと同等です。


変更可能なビューまたは変更不可能なビューの作成

多くの場合、リストがread-onlyであれば十分です。多くの場合、結果のリストの内容は変更されませんが、リストを読み取るだけの下流の処理に渡されるだけです。

リストの変更を許可すると、いくつかの疑問が生じます。

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
于 2018-10-28T13:55:21.230 に答える
6

私はこれらの問題のために小さなライブラリを書いています:

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

気になる場合はこちらをチェックしてください

于 2010-01-31T22:04:18.880 に答える
6

Java 8 の別の方法。

long[] input = someAPI.getSomeLongs();
LongStream.of(input).boxed().collect(Collectors.toList()));
于 2016-08-25T09:56:11.603 に答える
4

Java 8の別の方法。

final long[] a = new long[]{1L, 2L};
final List<Long> l = Arrays.stream(a).boxed().collect(Collectors.toList());
于 2015-08-31T05:16:45.067 に答える
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);
于 2012-10-12T17:56:00.880 に答える
2

同様のセマンティクスArrays.asListが必要な場合は、 の顧客実装を記述する (または他の誰かのを使用する) 必要があります(ListおそらくAbstractList.Arrays.asList

于 2009-04-16T00:38:25.170 に答える
2

変換を使用できます:

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

たとえば、ソースがintの配列である場合にも機能します。

于 2010-01-20T06:10:29.983 に答える
1

新しいリストを作成し、(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

ここから入手してください: https://github.com/Sf298/Sauds-Toolbox/blob/master/src/main/java/PrimitiveArrayWrapper/PrimitiveList.java

注: まだ完全にはテストしていないので、バグや問題が見つかったらお知らせください。

于 2019-06-16T05:33:46.950 に答える