0

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.

Sophia
  • 81
  • 4
  • How about `.filter()` to exclude the pairs that don't have equal elements? – ernest_k May 09 '22 at 07:43
  • So I need to make sure they have the same elements, otherwise throw an exception. But how do we even filter out the pairs don't have equal elements? – Sophia May 09 '22 at 07:49
  • *the keys of the pairs are the same? Since I need to make sure they are the same before proceeding to the next step* - Can you specify what means *keys are the same*? Does it mean that both values in each pair have to be equal, or need to check whether all the pairs share the same key, or you need to group all pair by key? Please [edit the question](https://stackoverflow.com/posts/72168514/edit). For now, it is unclear you are trying to achieve. – Alexander Ivanchenko May 09 '22 at 11:27

2 Answers2

1

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.

Ashish Patil
  • 4,428
  • 1
  • 15
  • 36
1

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.

MC Emperor
  • 22,334
  • 15
  • 80
  • 130