Setインスタンスがあります:
Set<String> siteIdSet = (Set<String>) pContext.getParent().getPropertyValue(getCatalogProperties().getSitesPropertyName());
pContext.getParent().getPropertyValue()
はすぐに使用できるコードであり、変更するコントロールはありません。
firstデフォルト要素を(常に)取り出したいと思いました。しかし、ArrayList
のようなメソッドget(index)
が見つかりませんでした。
したがって、今、私はこのようにしています。
for (Iterator<String> it = siteIdSet.iterator(); it.hasNext();) {
siteId = it.next();
break;
}
これを達成するための(他の)効率的な方法(短くて良い)はありますか?
Oracle docs から:
その名前が示すように、このインターフェイスは数学的なset抽象化をモデル化します。
Set Theory では、「「セット」は、それ自体がオブジェクトと見なされる別個のオブジェクトのコレクションです。」 - [Wikipedia-Set] 。
数学的には、セット内の要素は個別化されていません。それらの唯一のアイデンティティは、セット内の存在から派生します。したがって、概念的にそのようなタスクは非論理的であるため、セットの「最初の」要素を取得しても意味がありません。
セットから「最初の」要素を取得しても意味がない場合がありますが、必要なのは、セットから1つのオブジェクトを取得することだけです(どのオブジェクトであるかは保証されません)。
for(String aSiteId: siteIdSet) {
siteId = aSiteId;
break;
}
これはSet
の「最初の」オブジェクトを取得するために(投稿した方法よりも)少し短い方法ですが、イテレータはまだ(フードの下で)作成されているため、パフォーマンス上のメリットはありません。
これは最初の要素を返します
set.iterator().next();
または、Java8を使用:
Object firstElement = set.stream().findFirst().get();
そして、あなたはすぐにそれで何かをすることができます:
set.stream().findFirst().ifPresent(<doStuffHere>);
または、要素が欠落している場合に代替を提供したい場合(私の例では新しいデフォルト文字列を返します):
set.stream().findFirst().orElse("Empty string");
最初の要素が欠落している場合でも、例外をスローできます。
set.stream().findFirst().orElseThrow(() -> new MyElementMissingException("Ah, blip, nothing here!"));
最初の要素を最初に取得する以外の例を提供するように促してくれたAlex Vulaj
に感謝します。
セットは、アイテムの一意のコレクションです。したがって、最初の要素の概念はありません。ソートされた順序でアイテムが必要な場合は、 TreeSet を使用できます。そこから TreeSet#first() を使用して最初の要素を取得できます。
呼び出し TreeSet::first
要素を移動し、first()
を呼び出します。
new TreeSet<String>(
pContext.getParent().getPropertyValue( … ) // Transfer elements from your `Set` to this new `TreeSet`, an implementation of the `SortedSet` interface.
).first()
Set
には順序がありません他の人が言ったように、定義により Set
には順序がありません。したがって、「最初の」要素を要求しても意味がありません。
Set
の一部の実装には、アイテムが追加された順序などの順序があります。その非公式な注文は、 Iterator
で入手できます。しかし、その順序は偶然であり、保証されていません。運がよければ、Set
をサポートする実装は、実際にはSortedSet
である可能性があります。
CAVEAT:順序が重要な場合、そのような動作に依存しないでください。信頼性が重要でない場合、そのような文書化されていない動作は便利です。 Set
を指定した場合、他に実行可能な代替手段はありません。したがって、これを試すことは何もしないよりはましです。
Object firstElement = mySet.iterator().next();
質問に直接対処するには...いいえ、空のSetの可能性のあるケースを処理しながらイテレータから最初の要素を取得する実際の短い方法ではありません。ただし、質問のif
ループではなく、isEmpty
に対してfor
テストを使用することをお勧めします。
if ( ! mySet.isEmpty() ) {
Object firstElement = mySet.iterator().next();
)
SortedSet
を使用Set
でソート順を維持する場合は、 SortedSet
実装を使用します。そのような実装には以下が含まれます。
TreeSet
。ConcurrentSkipListSet
。SortedSetMultimap
クラスは SortedSet
メソッドからasMap
を返します。LinkedHashSet
を使用必要なのは、Set
に追加された順序で要素を記憶することだけである場合は、 LinkedHashSet
を使用します。
ドキュメントを引用するには、このクラス…
すべてのエントリを介して実行される二重リンクリストを維持します。このリンクリストは、要素がセットに挿入された順序(挿入順序)である反復順序を定義します。
として、あなたはpContext.getParent().getPropertyValue
return Set
を述べました。 Set
をList
に変換して、最初の要素を取得できます。次のようにコードを変更するだけです:
Set<String> siteIdSet = (Set<String>) pContext.getParent().getPropertyValue(..);
List<String> siteIdList=new ArrayList<>(siteIdSet);
String firstItem=siteIdList.get(0);
Set
は順序付けを強制しません。質問で行ったようにHashSet
に対してイテレータを使用しても、常に「最初の」要素を取得する保証はありません。
予測可能な順序付けが必要な場合は、 LinkedHashSet
実装を使用する必要があります。 LinkedHashSetを反復処理すると、挿入した順序で要素が取得されます。 get
にLinkedHashSet
メソッドがあると、どこでも具象クラスを使用する必要があるため、イテレーターを使用する必要があります。
要素にアクセスするには、イテレータを取得する必要があります。しかし、Iteratorは、例外的な場合を除き、特定の順序での保証は行いません。そのため、最初の要素を取得するのは確実ではありません。
これは動作します:
Object firstElement = set.toArray()[0];
これは私が先日自分自身に出くわした難しい質問です。 Java.util.LinkedHashSet
は、コンテンツのリンクリスト(デフォルトでは追加順)を維持しますが、アクセサーは提供しません。他の構造タイプは、add()
、remove()
、およびcontains()
でO(1)を提供できません。
LinkedHashSet
を使用してiterator()
を取得し、1つの要素を取得して破棄できます。多数の異なるセットに対して頻繁にこれを実行するときに速度やメモリをあまり気にしない場合、それはおそらくあなたの解決策です...加えて、私は少し余分に望ましい機能がありました。
最終的に、RandomAccessLinkedHashSet
と呼ばれる独自のクラスを作成しました。このクラスは、ハッシュテーブル、二重にリンクされたリスト、および順序に関係のない配列を同時に維持します。 Set
とDeque
の両方に準拠するように作成しましたが、Dequeの実装は、既に含まれているPush()
要素に失敗するため、少し大ざっぱです。インターフェースの契約。 3番目の構造である配列を維持することは、あなたがしていることにまったく必要ではありませんが、セット内のrandom要素へのアクセスも許可しますどんな容量でも、実際にランダムな値を提供できます。
興味があれば、このソースを提供できます。まだSerialized
ではありませんが、実行時には問題なく動作します。
何らかの方法で提供されるSet
のタイプを保証できない場合は、Iterator
を使用する必要があります。
ベクターには便利な機能がいくつかあります。
Vector<String> siteIdVector = new Vector<>(siteIdSet);
String first = siteIdVector.firstElement();
String last = siteIdVector.lastElement();
しかし、私は同意します-基本セットが注文されることが保証されていないため、これは意図しない結果をもたらす可能性があります。
定義による設定は順序付けられていません。
おそらく間違ったコレクションを使用しています。
Setから最初の要素を取得しても意味がありません。このような要件がある場合は、セットの代わりにArrayListを使用してください。セットは重複を許可しません。それらには個別の要素が含まれています。