Iterableを使用してJavaでSet Implementation(HashSet)を初期化したいとします。しかし、HashSetのコンストラクタはIterablesを受け入れず、Collections型のオブジェクトだけを受け入れます。Iterableを使用してセットを初期化する
Iterableからいくつかのサブタイプのコレクションに変換する方法はありますか。
Iterableを使用してJavaでSet Implementation(HashSet)を初期化したいとします。しかし、HashSetのコンストラクタはIterablesを受け入れず、Collections型のオブジェクトだけを受け入れます。Iterableを使用してセットを初期化する
Iterableからいくつかのサブタイプのコレクションに変換する方法はありますか。
HashSet
コンストラクタは、Iterable
が提供するもの以上のものに依存しています。コレクションの先頭にあるsize
を最適に知りたい基礎となるHashMap
を構築する。サイズがわからない真実で控えめなIterable
がある場合は、多くの明白な方法のいずれかでそれを普通のCollection
に変えることでIterable
を前もって実現する必要があります。
一方、すでにサイズがわかっているより豊富なオブジェクトがある場合は、Iterable
をコレクションにラップするミニマリストのアダプタクラスを作成し、呼び出しを転送するだけでsize
を実装しますiterator
。
public class IterableCollection<T> implements Collection<T>
{
private final Iterable<T> iterable;
public IterableCollection(Iterable<T> it) { this.iterable = it; }
@Override public Iterator<T> iterator() { return iterable.iterator(); }
@Override public int size() { return ... custom code to determine size ... }
@Override .... all others ... { throw new UnsupportedOperationException(); }
}
それぞれを追加するだけです。
public static <T> Set<T> setFromIterable(Iterable<T> i) {
HashSet<T> set = new HashSet<T>();
Iterator<T> it = i.iterator();
while (it.hasNext()) {
set.add(it.next());
}
return set;
}
Iterable<Integer> someIterable = ...;
Set<Integer> someSet = setFromIterable(someIterable);
それが存在しないため、あなたは、コンストラクタnew HashSet<Integer>(someIterator)
を使用しないでください注意。静的メソッドを呼び出すだけです。
私はあなたが「Iterable」と「Iterator」を混乱させると思います。 –
はい、そうです。しかしiterator()は動作しません。私が持っているオブジェクトもIterator()を返しますが、コンストラクタには受け入れられません。 – VaidAbhishek
カーク:そうです。ありがとう。 @Vaidは私の編集を見てください。 – wchargin
確かに、this答えで示されています。基本的には、反復可能を反復処理し、コレクションにその内容をコピーします。次のように
public static <T> List<T> copyIterable(Iterable<T> iterable) {
Iterator<T> iter = iterable.iterator();
List<T> copy = new ArrayList<T>();
while (iter.hasNext())
copy.add(iter.next());
return copy;
}
は、それを使用して、結果のList
オブジェクトはHashSet
コンストラクタにパラメータとして渡すことができます。
Iterable<Integer> list = Arrays.asList(1, 2, 3);
List<Integer> copy = copyIterable(list);
Set<Integer> aSet = new HashSet<Integer>(copy);
EDIT
私はすべてに沿って誤解されてきました。 Iterable
はCollection
のスーパーインターフェイスなので、Iterable
がCollection
で始まっていればシンプルな(ただし安全ではない)キャストがトリックを行います。
Iterable<Integer> list = Arrays.asList(1, 2, 3);
Set<Integer> aSet = new HashSet<Integer>((Collection)list); // it works!
Downovoter:コメントしますか? –
Iterableを明示的に反復すること、またはIteratorを自分自身で消費することは避けていました。私は、それがHashSetのコンストラクタまたはSet Implementationに受け入れられるように、メカニズムを探しています。 (私はあなたに投票しませんでした)。しかし、私に回避策を教えてもらうと、私は間違いなくあなたを失望させるでしょう。 :-) – VaidAbhishek
これはIterableではなくIteratorを受け入れます。 – wchargin
あなたはGuavaを使用することができます。
Set<T> set = Sets.newHashSet(iterable);
か、それは文、静的インポートのように読めるようにする、
import static com.google.common.collect.Sets.*;
Set<T> set = newHashSet(iterable);
Iterableインターフェースは "foreachの" 構文が作業することができますので、クリーンな方法がありそうです:
public <T> Set<T> toSet(Iterable<T> collection) {
HashSet<T> set = new HashSet<T>();
for (T item: collection)
set.add(item);
return set;
}
良い説明。私はあなたのポイントと直感を得ると思います。 – VaidAbhishek