配列から可変リストを作成しますか?


85

配列Listの内容を変更するために、に変換したい配列があります。

スタックオーバーフローは、アドレスという質問/回答のたくさん持っているArrays.asList()とどのようにそれが唯一の根本的な配列のリストビューを提供し、そしてどのように結果の一覧を操作しようとすると、一般的にスローされますUnsupportedOperationException(例えば、リストを操作するために使用される方法としてadd()remove()など)があるがによって提供されるリスト実装では実装されていませんArrays.asList()

しかし、配列を可変リストに変換する方法の例を見つけることができません。配列とput()各値をループして新しいリストに入れることができると思いますが、これを行うためのインターフェイスが存在するかどうか疑問に思っています。

回答:


122

1つの簡単な方法:

Foo[] array = ...;
List<Foo> list = new ArrayList<Foo>(Arrays.asList(array));

これにより、変更可能なリストが作成されますが、元の配列のコピーになります。リストを変更しても、配列変更されません。もちろん、を使用して後でコピーして戻すことができますtoArray

配列に可変ビューを作成したい場合は、それを自分で実装する必要があると思います。


2
これらの変異の方法は、リストのサイズは影響しないよう、サポートしては、Arrays.asListは、アレイ上にビューを返します
ティモWestkämper

1
@ jon-skeet私が知っているのは、Arrays.asListは、可変性が制限された配列に基づくリストを提供するということです。追加/削除/挿入が必要な場合は、ArrayListラッピングの方が適しています。
ティモWestkämper

4
Javaは、これらすべての静的ファクトリメソッドで可変性/不変性を明確にする必要があります。実行時に不変のものを作成したことを知るのは残念です。
dustinevan

1
@dustinevan:ドキュメントは非常に明確ですIMO:「指定された配列に裏打ちされた固定サイズのリストを返します。(返されたリストへの変更は配列に「ライトスルー」します。)」
JonSkeet18年

1
@JonSkeetはあなたの時間を無駄にしたくありません-あなたがするすべてに感謝します。名前自体をより明確にするために投票したいのですが、ドキュメントは明確だと確信しています。私たちの何人かは言語間で踊っています、そしてこれは他の言語ではかなり明白です。
dustinevan

23

また、GoogleコレクションAPI(Guava)を使用している場合:

Lists.newArrayList(myArray);

1
これが最も簡潔な答えです。ありがとう。
eugene82 2015年

2
Guava自体でさえnew ArrayList<>(Arrays.asList(...))、どちらかを使用することをお勧めします-メソッドのjavadocは、十分に有用ではないため、非推奨になることを意味します。
ローガンピックアップ

1
2020年であり、まだ非推奨ではありません。飛び込んで!
markthegrea

13

Java8に含まれているStreamAPIを使用するこの単純なコードは、配列の要素を含む可変リスト(またはビュー)を作成します。

Foo[] array = ...;
List<Foo> list = Stream.of(array).collect(Collectors.toCollection(ArrayList::new));

または、同様に有効です。

List<Foo> list = Arrays.stream(array).collect(Collectors.toCollection(ArrayList::new));

4

あなたが使用している場合はEclipseのコレクション(旧GSコレクションを)は、使用することができますFastList.newListWith(...)FastList.wrapCopy(...)

どちらのメソッドも可変引数を使用するため、配列をインラインで作成するか、既存の配列を渡すことができます。

MutableList<Integer> list1 = FastList.newListWith(1, 2, 3, 4);

Integer[] array2 = {1, 2, 3, 4};
MutableList<Integer> list2 = FastList.newListWith(array2);

2つの方法の違いは、配列がコピーされるかどうかです。newListWith()配列をコピーしないため、一定の時間がかかります。アレイが他の場所で変更される可能性があることがわかっている場合は、使用を避ける必要があります。

Integer[] array2 = {1, 2, 3, 4};
MutableList<Integer> list2 = FastList.newListWith(array2);
array2[1] = 5;
Assert.assertEquals(FastList.newListWith(1, 5, 3, 4), list2);

Integer[] array3 = {1, 2, 3, 4};
MutableList<Integer> list3 = FastList.wrapCopy(array3);
array3[1] = 5;
Assert.assertEquals(FastList.newListWith(1, 2, 3, 4), list3);

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


1
それはあなたがそこに持っている素晴らしいコレクションAPIです。私が最初に見たものは、私自身の実装から私を誘惑するかもしれません...私が一般的に役立つと思うのは、配列に裏打ちされたソートされたセットの実装だけです(私が見つけたものは、めったに変更されないデータ、または頻繁に変更される可能性があるが通常は10個程度の要素しか保持しないセットのいずれかのツリーベースの実装。
ジュール

0
myNewArrayList = new ArrayList<>(Arrays.asList(myArray));

1
@JonSkeetあなたのコメントは2012年のもので、将来はリヴィンですが、私のIDEが特に強調し、「ねえ、これを宣言しないでください」と言っていることを考えると、このコメントはうまく機能していないと思います。宣言されたタイプ。そこには必要ありません」?
BrentThoenen19年

1
@BrentThoenen:あなたのコメントがわかりません。私のコメントがリビジョン1 myNewArrayList = new ArrayList(...)、つまりraw型を使用していることに気づきましたか?「diamond演算子を使用してコンパイラに型引数を処理させる」と「raw型を使用する」には違いがあります。
ジョンスキート

1
私はこの回答を投稿し、@ JonSkeet自身が私の回答にコメントしたことをずっと忘れていました。コメントしてくれてありがとうブレント。
シド

@JonSkeetああ、私の悪い。あなたがコメントしているリビジョンをチェックしませんでした。私は、2012javaが空のdiamond演算子もraw型として想定しているという誤った想定をしました。それが私のbです。答えてくれてありがとう!
BrentThoenen19年

0

Streams APIを使用して別のオプションを追加する:

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

2
ソリューションの問題は、Collectors#toListに可変性の保証がないため、要件に適合しないことです。
MikaelF
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.