たとえば、int、int [] fooなどのプリミティブの配列があります。それは小さなものかもしれませんし、そうでないかもしれません。
int foo[] = {1,2,3,4,5,6,7,8,9,0};
それからIterable<Integer>
を作成する最良の方法は何ですか?
Iterable<Integer> fooBar = convert(foo);
ノート:
ループを使用して答えないでください(コンパイラーがループに対してスマートに何かを行う方法について適切な説明を提供できる場合を除く)。
また、
int a[] = {1,2,3};
List<Integer> l = Arrays.asList(a);
コンパイルさえしません
Type mismatch: cannot convert from List<int[]> to List<Integer>
また、答える前に なぜ配列がIterableに割り当てられないのですか? も確認してください。
また、何らかのライブラリ(グアバなど)を使用する場合は、これがなぜベストなのかを説明してください。 (Googleからの完全な回答ではないため:P)
最後に、それについて宿題があるように見えるので、宿題のコードを投稿しないでください。
Integer foo[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
List<Integer> list = Arrays.asList(foo);
// or
Iterable<Integer> iterable = Arrays.asList(foo);
ただし、これを機能させるにはInteger
配列(int
配列ではない)を使用する必要があります。
プリミティブには、グアバを使用できます。
Iterable<Integer> fooBar = Ints.asList(foo);
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>15.0</version>
<type>jar</type>
</dependency>
Java8の場合:(Jin Kwonの回答より)
final int[] arr = {1, 2, 3};
final PrimitiveIterator.OfInt i1 = Arrays.stream(arr).iterator();
final PrimitiveIterator.OfInt i2 = IntStream.of(arr).iterator();
final Iterator<Integer> i3 = IntStream.of(arr).boxed().iterator();
ちょうど私の2セント:
final int a[] = {1,2,3};
Java.lang.Iterable<Integer> aIterable=new Iterable<Integer>() {
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
private int pos=0;
public boolean hasNext() {
return a.length>pos;
}
public Integer next() {
return a[pos++];
}
public void remove() {
throw new UnsupportedOperationException("Cannot remove an element of an array.");
}
};
}
};
Java 8を使用すると、これを実行できます。
final int[] arr = {1, 2, 3};
final PrimitiveIterator.OfInt i1 = Arrays.stream(arr).iterator();
final PrimitiveIterator.OfInt i2 = IntStream.of(arr).iterator();
final Iterator<Integer> i3 = IntStream.of(arr).boxed().iterator();
Guavaは、必要なアダプターを Int.asList() として提供します。関連するクラスの各プリミティブ型に相当するものがあります(例:Booleans
の場合はboolean
など).
int foo[] = {1,2,3,4,5,6,7,8,9,0};
Iterable<Integer> fooBar = Ints.asList(foo);
for(Integer i : fooBar) {
System.out.println(i);
}
Arrays.asList
を使用するための上記の提案は、たとえIterator<int[]>
ではなくIterator<Integer>
を取得するためにコンパイルされても機能しません。何が起こるかというと、配列を基にしたリストを作成するのではなく、配列を含む1要素の配列リストを作成したということです。
私は同じ問題を抱えていて、次のように解決しました:
final YourType[] yourArray = ...;
return new Iterable<YourType>() {
public Iterator<YourType> iterator() {
return Iterators.forArray(yourArray); // Iterators is a Google guava utility
}
}
イテレータ自体は怠__なUnmodifiableIterator
ですが、それがまさに私が必要としたものです。
まず第一に、Arrays.asList(T...)
がWrapper型または非プリミティブデータ型を持つ配列の最適なソリューションであることは明らかです。このメソッドは、基本的にAbstractList
クラスの単純なプライベート静的Arrays
実装のコンストラクターを呼び出します。これは、基本的に指定された配列参照をフィールドとして保存し、必要なメソッドをオーバーライドしてリストをシミュレートします。
配列にプリミティブ型またはWrapper型を選択できる場合、このような状況にはWrapper型を使用しますが、もちろん、必ずしも便利または必須というわけではありません。できることは2つだけです。
1)各プリミティブデータ型配列の静的メソッドを使用してクラスを作成できます(boolean, byte, short, int, long, char, float, double
がIterable<
WrapperType>
を返します。これらのメソッドは、Iterator
の匿名クラスを使用します(Iterable
以外)。メソッドを実装するためのフィールドとしての引数(たとえばint[]
)。
->このアプローチはパフォーマンスが高く、メモリを節約します(ただし、Arrays.asList()
を使用すると同じ方法でメモリが消費されますが、新しく作成されたメソッドのメモリは除きます
2)配列にはメソッドがないため(リンクした側で読み取られるため)、Iterator
インスタンスも提供できません。新しいクラスを書くのが面倒な場合は、Iterable
またはサブタイプをインスタンス化する以外に方法がないため、Iterable
を実装する既存のクラスのインスタンスを使用する必要があります。Iterable
を実装する既存のコレクション派生物を作成する唯一の方法は、ループを使用するか(上記の匿名クラスを使用する場合を除く)、またはコンストラクターがプリミティブ型配列を許可するIterable
実装クラスをインスタンス化することです(Object[]
ができないため) tはプリミティブ型の要素を持つ配列を許可します)が、私の知る限り、Java APIにはそのようなクラスはありません。
ループの理由は簡単に説明できます。
必要なコレクションごとにオブジェクトとプリミティブデータ型はオブジェクトではありません。オブジェクトはプリミティブ型よりもはるかに大きいため、プリミティブ型配列の各要素に対して生成する必要がある追加データが必要です。つまり、3つの2つの方法(Arrays.asList(T...)
を使用するか、既存のコレクションを使用する)でオブジェクトの集約が必要な場合、int[]
配列のプリミティブ値ごとにラッパーオブジェクトを作成する必要があります。 3番目の方法では、配列をそのまま使用し、匿名クラスで使用します。高速なパフォーマンスのために望ましいと思うからです。
配列またはObject
を使用するメソッドの引数としてIterable
を使用する3番目の戦略もあり、引数がどの型であるかを判別するために型チェックが必要になりますが、お勧めしませんオブジェクトが常に必要な型であるとは限らず、特定の場合には別個のコードが必要であると通常考慮する必要があるためです。
結論として、単純なArrays.asList(T...)
を使用して多くのコードを節約する一般的な型としてプリミティブ型を使用できないのは、Javaの問題のある一般的な型システムの障害です。したがって、プリミティブ型の配列ごとにプログラムする必要があります。そのようなメソッド(基本的に、使用される型引数ごとに別個のメソッドを作成するC++プログラムで使用されるメモリに違いはありません)。
IterableOf
from Cactoos を使用できます。
Iterable<String> names = new IterableOf<>(
"Scott Fitzgerald", "Fyodor Dostoyevsky"
);
次に、 ListOf
を使用してリストに変換できます。
List<String> names = new ListOf<>(
new IterableOf<>(
"Scott Fitzgerald", "Fyodor Dostoyevsky"
)
);
または単にこれ:
List<String> names = new ListOf<>(
"Scott Fitzgerald", "Fyodor Dostoyevsky"
);
同様の回答がすでに投稿されていますが、新しいPrimitiveIterator.OfIntを使用する理由は明確ではなかったと思います。よい解決策は、Java 8 PrimitiveIteratorを使用することです。これは、プリミティブなint型に特化されているためです(そして、余分なボクシング/アンボクシングペナルティが回避されます)。
int[] arr = {1,2,3};
// If you use Iterator<Integer> here as type then you can't get the actual benefit of being able to use nextInt() later
PrimitiveIterator.OfInt iterator = Arrays.stream(arr).iterator();
while (iterator.hasNext()) {
System.out.println(iterator.nextInt());
// Use nextInt() instead of next() here to avoid extra boxing penalty
}
参照: https://doc.bccnsoft.com/docs/jdk8u12-docs/api/Java/util/PrimitiveIterator.OfInt.html