Sophia
Sophia

Reputation: 81

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.

Upvotes: 0

Views: 132

Answers (2)

MC Emperor
MC Emperor

Reputation: 23037

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.

Upvotes: 1

Ashish Patil
Ashish Patil

Reputation: 4624

You wanted to thrown exception within same call, then this is another way within single call:

Stream.of(string1, string2).map(this::function1).reduce((p, q) -> {
        if (p.getKey().compareTo(q.getKey())==0)
            return p;
        else
            return null;
    }).orElseThrow(() -> new Exception("keys don't match"));

Please note you are going to return Optional<Pair<Integer, Integer>> here if value matches.

Upvotes: 1

Related Questions