私はxから始まるセットからn個の要素を取得する最もエレガントな方法を見つけようとしていました。私が結論付けたのはストリームを使用することでした:
Set<T> s;
Set<T> subS = s.stream().skip(x).limit(n).collect(Collectors.toSet());
これは、この方法で行うのに最適な方法ですか?欠点はありますか?
Guava、Iterables.limit(s, 20)
を使用します。
コードが機能しません。
Set<T,C> s; Set<T,C> subS = s.stream().skip(x).limit(n).collect(Collectors.toSet());
とは Set<T,C>
? Set
には特定のタイプの要素が含まれているので、twoタイプのパラメーターは何を意味するのですか?
さらに、Set<T>
、定義された順序はありません。 「xから始まるセットのn個の要素」は、Set
のコンテキストでは意味がありません。いくつかの特殊なSet
実装があり、順序があります。はソートされるか挿入順序を保持しますが、コードはそのような前提条件を宣言していませんが、任意のSet
で動作するように思われるため、壊れていると見なす必要があります。
Set
の一部を注文に従って処理する場合は、最初に注文を凍結する必要があります。
Set<T> s;
List<T> frozenOrder=new ArrayList<>(s);
リストには、Set
の作成時に固定された、または任意の順序がある場合、ArrayList
の順序になります。この順序は後で変更されません。
次に、そのフラグメントを抽出するのは簡単です:
List<T> sub=frozenOrder.subList(x, Math.min(s.size(), x+n));
必要に応じて、Set
に戻すこともできます。
Set<T> subSet=new HashSet<>(sub);
とはいえ、位置番号で指定されたSet
の一部を処理することはかなり珍しいことです。
セットを繰り返し処理して、最初のn個の要素を収集できます。
int n = 0;
Iterator<T> iter = set.iterator();
while (n < 8 && iter.hasNext()) {
T t = iter.next();
list.add(t);
n++;
}
利点は、より一般的なソリューションよりも高速であることです。
欠点は、提案したものよりも冗長であることです。
セットは、元の方法では、要素を順序付けすることを目的としていないため、要素xから開始することはできません。 SortedSetは、使用する「セット」である場合があります。
最初にリストに変換します。
_ new ArrayList(s).subList(<index of x>, <index of x + n>);
_
ただし、パフォーマンスに非常に悪い影響を与える可能性があります。この場合、明示的な順序がないため、ArrayListを格納して次のsubListを取得する必要があり、暗黙の順序は、次回new ArrayList(s)
が呼び出されたときに変更される可能性があります。
Stream
の使用は問題ありません。私が見ることができる1つの欠点は、Set
のすべての実装が順序付けされているわけではないことです。 HashSet
は順序付けされていませんが、LinkedHashSet
は順序付けされています。 SO実行ごとに結果セットが異なる場合があります。
まず、セットはその特定の要素を取得するために作成されていません。代わりに、sortedSetまたはArrayListを使用する必要があります。
ただし、セットの要素を取得する必要がある場合は、次のコードを使用してセットを反復できます。
int c = 0;
int n = 50; //Number of elements to get
Iterator<T> iter = set.iterator();
while (c<n && iter.hasNext()) {
T t = iter.next();
list.add(t);
c++;
}