web-dev-qa-db-ja.com

Java Set?

単純な_Set<T>_が与えられた場合、Setからany値を取得する良い方法(高速、数行のコード)は何ですか?

Listを使用すると、簡単です。

_List<T> things = ...;
return things.get(0);
_

ただし、Setの場合、Setsは順序付けされていないため、.get(...)メソッドはありません。

54
Jacob Marble

Set<T>Iterable<T>、したがって、最初の要素への反復が機能します。

Set<T> things = ...;
return things.iterator().next();

グアバには メソッド がありますが、上記のスニペット おそらくより良い です。

75
Jacob Marble

ストリームが存在するため、そのようにすることもできますが、クラスJava.util.Optionalを使用する必要があります。 Optionalは、要素のラッパークラスまたは明示的に要素なし(Nullpointerを回避)です。

//returns an Optional.
Optional <T> optT = set.stream().findAny();

//Optional.isPresent() yields false, if set was empty, avoiding NullpointerException
if(optT.isPresent()){
    //Optional.get() returns the actual element
    return optT.get();
}
4
Dániel Somogyi

SetまたはCollectionからany要素を取得することは、arbitrary意的または折not的でないとしても、珍しい要求のように思えるかもしれませんが、たとえば、計算する必要がある場合は非常に一般的です MapsのKeysまたはValuesオブジェクトの統計。最小値/最大値を初期化する必要があります。 Set/Collection(Map.keySet()またはMap.values()によって返される)のany要素は、min/max値を更新する前にこの初期化に使用されますover =each要素。

それでは、この問題に直面し、同時にメモリと実行時間を小さくしてコードを明確にしようとするときに、どのような選択肢がありますか?

通常、「convert Set to ArrayList and get the first element」という通常の結果が得られます。すばらしいです! Setからのretrieveオブジェクト、allocate配列およびpopulateit:

HashMap<K,V> map;
List<K> list = new ArrayList<V>(map.keySet()); // min/max of keys
min = max = list.get(0).some_property(); // initialisation step
for(i=list.size();i-->1;){
 if( min > list.get(i).some_property() ){ ... }
 ...
}

または、イテレータでループを使用し、最小/最大を初期化する必要があることを示すフラグと、ループ内のすべての反復に対してそのフラグが設定されているかどうかを確認する条件文を使用します。これは、多くの条件付きチェックを意味します。

boolean flag = true;
Iterator it = map.keySet().iterator();
while( it.hasNext() ){
  if( flag ){
    // initialisation step
    min = max = it.next().some_property();
    flag = false;
  } else {
    if( min > list.get(i).some_property() ){ min = list.get(i).some_property() }
  ...
  }
}

または、ループの外側で初期化を行います。

HashMap<K,V> map;
Iterator it = map.keySet().iterator();
K akey;
if( it.hasNext() ){
  // initialisation step:
  akey = it.next();
  min = max = akey.value();
  do {
    if( min > list.get(i).some_property() ){ min = akey.some_property() }
  } while( it.hasNext() && ((akey=it.next())!=null) );
}

しかし、min/maxが必要なときはいつでも、プログラマーに代わって(そしてJVMに代わってIteratorをセットアップするために)この操作すべてに本当に価値がありますか?

丁寧に正しいol 'スポーツからの提案は、「配置または削除されたときに最小値と最大値を追跡するクラスでマップをラップすること」です。

別の状況があります。私の経験では、マップからanyアイテムだけが必要になります。 これは、マップに共通のプロパティを持つオブジェクトが含まれる場合です(そのマップ内のすべてのオブジェクトで同じです)。そのプロパティを読み取る必要があります。たとえば、同じ数の次元を持つ同じヒストグラムの保持ビンのマップがあるとします。このようなマップを考えると、同じ次元の別のヒストビンを作成するために、マップ内のちょうどanyのヒストビンの次元数を知る必要があるかもしれません。イテレータを再度セットアップし、next()を一度だけ呼び出した後に破棄する必要がありますか?私は、この状況に対する無口な正しい人の提案をスキップします。

そして、any要素を取得する際のすべての問題がメモリの重要性を低下させ、CPUサイクルが増加する場合、困難なコードを取得するために記述する必要があるすべてのコードについてはどうでしょうか。any要素を取得します。

any要素が必要です。あげてください!

1
bliako