これはちょっと簡単な、頭痛の種の質問かもしれませんが、私の最初の試みは驚くほど完全にうまくいきませんでした。私はプリミティブなlongの配列を取り、それをリストに変えたかったので、次のようにしました。
long[] input = someAPI.getSomeLongs();
List<Long> inputAsList = Arrays.asList(input); //Total failure to even compile!
これを行う正しい方法は何ですか?
これはちょっと簡単な、頭痛の種の質問かもしれませんが、私の最初の試みは驚くほど完全にうまくいきませんでした。私はプリミティブなlongの配列を取り、それをリストに変えたかったので、次のようにしました。
long[] input = someAPI.getSomeLongs();
List<Long> inputAsList = Arrays.asList(input); //Total failure to even compile!
これを行う正しい方法は何ですか?
回答:
Apache commons lang ArrayUtils(JavaDoc、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);
編集:コメントやその他の修正によって提案されたリストへの完全な変換を提供するように更新されました。
Arrays.asList(ArrayUtils.toObject(input))
おそらく簡単にできるからです。
List<Long> = Arrays.asList(inputBoxed)
が質問に含まれていたので、明白だと思ったので繰り返すのは冗長だと思ったので、私は間違っていたと思います...
Java 8以降では、そのためにストリームを使用できるようになりました。
long[] arr = {1,2,3,4};
List<Long> list = Arrays.stream(arr).boxed().collect(Collectors.toList());
stream
機能だけのために定義されint[]
、long[]
そしてdouble[]
。
LongStream.of(arr).boxed()...
。
Arrays.stream(arr).boxed().collect(Collectors.toList());
残念ながらこれは戻ることしかできませんList<Object>
import java.util.Arrays;
import org.apache.commons.lang.ArrayUtils;
List<Long> longs = Arrays.asList(ArrayUtils.toObject(new long[] {1,2,3,4}));
hallidaveとjpalecek持っている右のアイデア、反復配列オーバー-しかし、彼らはによって提供される機能の利点を取ることはありませんArrayList
。ので、リストのサイズが知られている。この場合には、作成したとき、あなたはそれを指定する必要がありますArrayList
。
List<Long> list = new ArrayList<Long>(input.length);
for (long n : input)
list.add(n);
このようにして、不要な配列は作成されず、破棄されるだけです。これらの配列はArrayList
短すぎることが判明しArrayList
、スペース要件を過大評価したために空の「スロット」が無駄になることはありません。もちろん、リストに要素を追加し続ける場合は、新しいバッキング配列が必要になります。
別の可能性として、Guavaライブラリはこれをとして提供Longs.asList()
し、他のプリミティブ型の同様のユーティリティクラスを備えています。
import com.google.common.primitives.Longs;
long[] input = someAPI.getSomeLongs();
List<Long> output = Longs.asList(input);
配列をリストに変換する方法について質問されました。これまでのほとんどの回答は、配列と同じ内容の新しいリストを作成する方法、またはサードパーティのライブラリを参照する方法を示していました。ただし、この種の変換には単純な組み込みオプションがあります。それらのいくつかはすでに他の回答でスケッチされています(例:これ)。ただし、ここで実装の自由度を指摘して詳しく説明し、潜在的な利点、欠点、および警告を示します。
少なくとも2つの重要な違いがあります。
オプションはここですばやく要約され、完全なサンプルプログラムがこの回答の下部に表示されます。
新しいリストの作成とアレイのビューの作成
結果が新しいリストである場合、他の回答からのアプローチの1つを使用できます。
List<Long> list = Arrays.stream(array).boxed().collect(Collectors.toList());
ただし、これを行うことの欠点を考慮する必要がありlong
ます。1000000の値を持つ配列は、約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));
さて、これは真のコピーであり、上に示したストリームベースのソリューションで実現されるものと同等です。
作成、変更ビューまたは変更不可能なビューを
多くの場合、リストが読み取り専用であれば十分です。結果のリストの内容は変更されないことが多く、リストを読み取るだけのダウンストリーム処理に渡されるだけです。
リストの変更を許可すると、いくつかの疑問が生じます。
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
私はこれらの問題のために小さなライブラリを書いています:
long[] input = someAPI.getSomeLongs();
List<Long> = $(input).toList();
PavelとTomの答えを組み合わせると、
@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);
}
};
}
同様のセマンティクスArrays.asList
が必要な場合は、List
(おそらくAbstractList
。を介して)の顧客実装を作成する(または他の誰かの実装を使用する)必要がArrays.asList
あります。実装はとほぼ同じで、box値とunbox値のみが必要です。
あなたはtransmorphを使うことができます:
Transmorph transmorph = new Transmorph(new DefaultConverters());
List<Long> = transmorph.convert(new long[] {1,2,3,4}, new TypeReference<List<Long>>() {});
たとえば、sourceがintの配列である場合にも機能します。
この質問は十分古いものですが、独自の変換メソッドを記述することもできます。
@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);
catch (ArrayIndexOutOfBoundsException ex) { /* Finished getting array elements */ }
あなたはひどい人です。
新しいリストを作成してそれにすべての値を(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
注:まだ十分にテストしていないため、バグや問題を見つけた場合はお知らせください。
LongStream
そのために使用できます
List<Long> longs = LongStream.of(new long[]{1L, 2L, 3L}).boxed()
.collect(Collectors.toList());