web-dev-qa-db-ja.com

Java 8 Streamsに重複が存在するかどうかを確認する方法は?

Java 8では、リストに重複が含まれているかどうかを確認する最良の方法は何ですか?

私のアイデアは次のようなものでした:

list.size() != list.stream().distinct().count()

それが最良の方法ですか?

39
pedrorijo91

コードはすべての要素を反復処理する必要があります。次のような単純な方法の重複がないことを確認したい場合

public static <T> boolean areAllUnique(List<T> list){
    Set<T> set = new HashSet<>();

    for (T t: list){
        if (!set.add(t))
            return false;
    }

    return true;
}

最初の一意でない要素が見つかるとすぐにfalseを提供できるため、より効率的です。

このメソッドは、 Stream#allMatch これも短絡(指定された条件を満たさない最初の要素に対してすぐにfalseを返します)

public static <T> boolean areAllUnique(List<T> list){
    Set<T> set = new HashSet<>();
    return list.stream().allMatch(t -> set.add(t));
}

または @ Holger コメントで言及

public static <T> boolean areAllUnique(List<T> list){
    return list.stream().allMatch(new HashSet<>()::add);
}
42
Pshemo

私は次を使用しました:
1。 return list.size() == new HashSet<>(list).size();

私はそれがどのように比較されるのか分かりません:
2。 return list.size() == list.stream().distinct().count();
そして
3。 return list.stream().sequential().allMatch(new HashSet<>()::add);
パフォーマンスの観点から。

最後のもの(#3)は、コレクション(リストなど)だけでなく、ストリームも(明示的に収集せずに)処理する可能性があります。

更新:最後の1つ(#3)は、純粋なストリームを処理できるだけでなく、最初の複製で停止するため(#1と#2は常に最後まで繰り返されるため)、最高のようです— @Pshemoとして コメント で述べました。

9
Sasha

カウントコレクターを使用できます。

Stream.of(1, 3, 4, 6, 7, 5, 6)
            .collect(Collectors.groupingBy(
                    Function.identity(), Collectors.counting()))
            .entrySet().stream().anyMatch(e -> e.getValue() > 1)
5
Will Humphreys

StreamToolとしてこのクラスを開始しましたが、reduceまたは類似のさらに良い方法が必要だと思います。

public class StreamTool {

    /**
     * Whether stream records are unique in that stream.
     * @param <T> Type of records
     * @param records
     * @return true if there are no duplicates, false otherwise
     */
    public static <T> boolean isUnique(Stream<T> records) {
        return records.allMatch(new HashSet<>()::add);
    }
}
2
geekdenz