javajava-stream

How to check if sub values of a mapped results are the same in Java stream?


I have the following stream transform:

Stream.of(string1, string2)
  .map(this::function1) // generate Stream<Pair<Integer, Integer>>

How to check the keys of the pairs are the same? Since I need to make sure they are the same before proceeding to the next step.


Solution

  • Well, the requirement looks like the one in this question, and Stuart Marks added an implementation to filter the stream based on distinct properties of an object.

    This is his code:

    public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Set<Object> seen = ConcurrentHashMap.newKeySet();
        return t -> seen.add(keyExtractor.apply(t));
    }
    

    However, we are not looking for filtering distinct values, but rather the opposite – object of which a specific property is the same as all others.

    I adapted the code so it throws an exception if the specified property of one of the objects is different than the others:

    static <T> Predicate<T> sameKeyOrThrow(Function<? super T, ?> keyExtractor, Supplier<RuntimeException> exceptionSupplier) {
        Set<Object> seen = ConcurrentHashMap.newKeySet();
        return t -> {
            seen.add(keyExtractor.apply(t));
            if (seen.size() > 1) {
                throw exceptionSupplier.get();
            }
            return true;
        };
    }
    

    Usage:

    Stream.of(string1, string2)
        .map(this::function1)
        .filter(sameKeyOrThrow(pair -> pair.left(), YourRuntimeException::new))
    

    The advantage of this method compared to collecting using Collectors::groupingBy is that it doesn't materialize the whole stream, but instead fails-fast if a distinct value is found.