67

float []があり、同じ要素のリストを取得したいと思います。それらを1つずつ追加するという醜いことはできましたが、Arrays.asListメソッドを使用したかったのです。しかし、問題があります。これは機能します:

List<Integer> list = Arrays.asList(1,2,3,4,5);

しかし、これはそうではありません。

int[] ints = new int[] {1,2,3,4,5};
List<Integer> list = Arrays.asList(ints);

asListメソッドは、私の知識の範囲では配列の「省略形」であるvarargsパラメーターを受け入れます。

質問:

  • 2番目のコードがを返すがを返さないのはなぜList<int[]>ですかList<int>

  • それを修正する方法はありますか?

  • ここでオートボクシングが機能しないのはなぜですか。すなわち?int[]_Integer[]

4

11 に答える 11

91

List<int>Javaにはそのようなものはありません-ジェネリックはプリミティブをサポートしていません。

オートボクシングは、プリミティブの配列ではなく、単一の要素に対してのみ発生します。

それを修正する方法については、このようなことを行うための方法がたくさんあるさまざまなライブラリがあります。これを回避する方法はありません。JDK内でこれを簡単にする方法はないと思います。ラッパータイプのリストでプリミティブ配列をラップするものもあれば(アクセス時にボックス化が行われるようにするため)、元の配列を反復処理して独立したコピーを作成し、ボックス化するものもあります。どちらを使用しているかを確認してください。

(編集:私は、の開始点はint[]交渉不可能であると想定していました。あなたがそれから始めることができるならInteger[]、あなたは十分に離れています:)

ヘルパーライブラリの一例として、Guavaを少しプラグインするために、がありcom.google.common.primitive.Ints.asListます。

于 2009-09-23T18:53:10.260 に答える
34

これはどう?

Integer[] ints = new Integer[] {1,2,3,4,5};
List<Integer> list = Arrays.asList(ints);
于 2009-09-23T18:52:15.433 に答える
18

Java配列はオブジェクトであり、int配列をvarargsリストの単一Arrays.asList()の引数として扱うためです。

于 2009-09-23T18:51:46.883 に答える
16

Java 8と入力すると、次のようにしてボックス化された配列に収集できます。

Integer[] boxedInts = IntStream.of(ints).boxed().toArray(Integer[]::new);

またはこれをボックスリストに収集します

List<Integer> boxedInts = IntStream.of(ints).boxed().collect(Collectors.toList());

ただし、これは、、、およびに対してのみ機能int[]long[]ますdouble[]。これはでは機能しませんbyte[]

Arrays.stream(ints)IntStream.of(ints)は同等であることに注意してください。したがって、前の2つの例は次のように書き直すこともできます。

Integer[] boxedIntArray = Arrays.stream(ints).boxed().toArray(Integer[]::new);
List<Integer> boxedIntList = Arrays.stream(ints).boxed().collect(Collectors.toList());

この最後の形式は、のプリミティブな特定のサブタイプを省略しているため、好まれる可能性がありStreamます。ただし、内部的にはまだオーバーロードされたものの束であり、この場合はまだIntStream内部的に作成されます。

于 2015-06-04T06:16:37.000 に答える
5

問題はではありませんArrays.asList()。問題は、オートボクシングが配列で機能することを期待していることですが、そうではありません。最初のケースでは、コンパイラーは、個々のintを自動ボックス化してから、それらが何に使用されているかを調べます。2番目のケースでは、最初にそれらをint配列に入れ(オートボクシングは不要)、次にそれをに渡しArrays.asList()ます(オートボクシングは不可能)。

于 2009-09-23T18:57:38.537 に答える
4

ここでオートボクシングが機能しないのはなぜですか。つまり、int[]からInteger[]?

オートボクシングはをに変換しますが、intをに変換しIntegerません。int[]Integer[]

なぜだめですか?

単純な(しかし満足のいくものではない)答えは、それがJLSの言うことだからです。(必要に応じて確認できます。)

本当の答えは、オートボクシングが何をしているのか、そしてなぜそれが安全なのかということの基本です。

1コード内のどこかでオートボックス化すると、同じオブジェクトが得られますInteger。これはすべての値に当てはまるわけではありませんが(オートボクシングキャッシュintのサイズが制限されているため)、オブジェクトの比較に使用すると、「正しい」答えが得られます。 IntegerequalsInteger

基本的N == Nには常に真実であり、new Integer(N).equals(new Integer(N))常に真実です。さらに、これら2つのことは真実のままです...純粋なJavaコードに固執すると仮定します。

今これを考慮してください:

int[] x = new int[]{1};
int[] y = new int[]{1};

これらは等しいですか?いいえ! x == y偽であり、x.equals(y)偽です!しかし、なぜ?なぜなら:

y[0] = 2;

つまり、Java配列は変更可能であるため、同じタイプ、サイズ、およびコンテンツの2つの配列は常に区別できます。

オートボクシングの「約束」は、結果が見分けがつかないので大丈夫だということです1。ただし、equalsfor配列と配列の可変性の定義により、すべての配列は基本的に区別できるためです。したがって、プリミティブ型の配列のオートボクシング許可された場合、それは「約束」を損なうことになります。


1 ==-.....オートボックス化された値が等しいかどうかをテストするために使用しない場合。

于 2018-07-22T02:01:38.193 に答える
3

Arrays.asList(T... a)事実上T[]、真のオブジェクト(のサブクラスObject)の任意の配列に一致するを配列として受け取ります。プリミティブ型はから派生しないため、そのように一致しないのはプリミティブの配列だけですObject。したがって、int[]はではありませんObject[]

次に何が起こるかというと、varagsメカニズムが起動し、それを単一のオブジェクトを渡したかのように扱い、そのタイプの単一の要素配列を作成します。int[][]したがって、 (ここでTは、)を渡してint[]、最終的に1要素List<int[]>になります。これは必要なものではありません。

ただし、まだかなり良いオプションがいくつかあります。

グアバのInt.asList(int[])アダプター

プロジェクトですでにguavaを使用している場合は、Guavaが提供するアダプター Int.asList()を使用するのと同じくらい簡単です。関連するクラスのプリミティブ型ごとに同様のアダプタがあります。たとえば、Booleansなどですboolean

int foo[] = {1,2,3,4,5};
Iterable<Integer> fooBar = Ints.asList(foo);
for(Integer i : fooBar) {
    System.out.println(i);
}

このアプローチの利点は、既存のアレイの周りに薄いラッパーを作成することです。そのため、ラッパーの作成は一定時間であり(アレイのサイズに依存しません)、必要なストレージはごくわずかな一定量です(基になる整数配列に加えて、100バイト未満)。

欠点は、各要素にアクセスするには、基になるのボックス化操作が必要intであり、設定にはボックス化解除が必要なことです。これにより、リストに頻繁にアクセスすると、一時的なメモリ割り当てが大量に発生する可能性があります。平均して各オブジェクトに何度もアクセスする場合は、オブジェクトを1回ボックス化して、として保存する実装を使用する方がよい場合がありますInteger。以下の解決策はそれを行います。

Java 8 IntStream

Java 8では、このArrays.stream(int[])メソッドを使用してint配列をに変換できStreamます。ユースケースによっては、ストリームを直接使用できる場合があります。たとえば、。を使用して各要素で何かを行うことができますforEach(IntConsumer)。その場合、このソリューションは非常に高速であり、ボックス化またはボックス化解除をまったく行わず、基になるアレイのコピーを作成しません。

または、本当に必要な場合は、ここで提案されているように使用List<Integer>できます。このアプローチの欠点は、リスト内のすべての要素を完全にボックス化することです。これにより、メモリフットプリントがほぼ一桁増加する可能性があり、ボックス化されたすべての要素を保持するための新しい要素が作成されます。その後、リストを頻繁に使用し、 sではなくオブジェクトが必要な場合、これは効果があるかもしれませんが、注意する必要があります。stream.boxed().collect(Collectors.toList())Object[]Integerint

于 2016-06-24T00:15:15.983 に答える
2

にを渡すint[]Arrays.asList()、作成されるリストはになりますがList<int[]>、これはJavaでは使用できず、正しいではありませんList<Integer>

私はあなたがArrays.asList()あなたのintを自動ボックス化することを期待していると思います、あなたが見てきたように、それはそうしません。

于 2009-09-23T18:55:36.813 に答える
2

に変換することはできませんint[]Integer[]値をコピーする必要があります


int[] tab = new int[]{1, 2, 3, 4, 5};
List<Integer> list = ArraysHelper.asList(tab);

public static List<Integer> asList(int[] a) {
    List<Integer> list = new ArrayList<Integer>();
    for (int i = 0; i < a.length && list.add(a[i]); i++);
    return list;
}
于 2010-07-27T04:24:39.777 に答える
0

または、EclipseコレクションIntListの型およびIntLists ファクトリとして使用して、値の配列から直接コレクションを作成することもできます。これにより、 toのボクシングが不要になります。intintInteger

IntList intList1 = IntLists.mutable.with(1,2,3,4,5);
int[] ints = new int[] {1,2,3,4,5};
IntList intList2 = IntLists.mutable.with(ints);
Assert.assertEquals(intList1, intList2);

Eclipseコレクションは、、、、および。Listだけでなく、可変および不変のプリミティブもサポートSetしています。BagStackMap

注:私はEclipseコレクションのコミッターです。

于 2019-11-03T00:43:49.250 に答える
0

intプリミティブ型です。Arrays.asList()は、プリミティブではなく、参照型(オブジェクト型)でのみ機能するジェネリック型Tを受け入れます。int []は全体としてオブジェクトであるため、単一の要素として追加できます。

于 2021-02-12T04:55:39.803 に答える