2017-08-31 1 views

答えて

7

なぜストリームがありますか?あなただけのリストのサイズに0から乱数を取得し、このインデックスにgetを呼び出す必要があります:

Random r = new Random(); 
ElementType e = list.get(r.nextInt(list.size()); 

ストリームが面白いここであなたに何も与えないでしょうが、あなたが試すことができます:

Random r = new Random(); 
ElementType e = list.stream().skip(r.nextInt(list.size()-1).findFirst().get(); 

アイデアは、任意の数の要素をスキップします(最後の要素ではありません!)、最初の要素があれば取​​得します。その結果、Optional<ElementTypeは空ではなく、getでその値を抽出します。スキップした後、ここにはたくさんのオプションがあります。ここでストリームを使用すると、非常に非効率的である

...

注:これらのソリューションのいずれもアカウントの空のリストにかかりませんが、問題は非空のリストに定義されていること。あなたはストリームを使用するを持っている場合

+0

空です。 – Andrew

+0

@AndrewTobilko Okですが、空のリストからランダムな要素を抽出することは、常に定義されていません。あなたの解決策にも同じです... –

+0

@ Jean-BaptisteYunés、感謝します、ありがとう。 – aekber

3

は、私が仕事をして、非常に非効率的なコレクターはいえ、エレガントを書いた:

/** 
* Returns a random item from the stream (or null in case of an empty stream). 
* This operation can't be lazy and is inefficient, and therefore shouldn't 
* be used on streams with a large number or items or in performance critical sections. 
* @return a random item from the stream or null if the stream is empty. 
*/ 
public static <T> Collector<T, List<T>, T> randomItem() { 
    final Random RANDOM = new Random(); 
    return Collector.of(() -> (List<T>) new ArrayList<T>(), 
           (acc, elem) -> acc.add(elem), 
           (list1, list2) -> ListUtils.union(list1, list2), // Using a 3rd party for list union, could be done "purely" 
           list -> list.isEmpty() ? null : list.get(RANDOM.nextInt(list.size()))); 
} 

使用法:それはリスト場合はNoSuchElementExceptionを生成します

@Test 
public void standardRandomTest() { 
    assertThat(Stream.of(1, 2, 3, 4).collect(randomItem())).isBetween(1, 4); 
} 
関連する問題