Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I need to map IntStream to Stream<Character>

  public static int construction(String myString) {
      Set<Character> set = new HashSet<>();

      int count = myString.chars()  // returns IntStream
      .mapToObj(c -> (char)c)       // Stream<Character> why is this required?
      .mapToInt(c -> (set.add(c) == true ? 1 : 0)) // IntStream
      .sum();

      return count;
    }

The above code will not compile without:

.mapObj(c -> (char)c)
// <Character> Stream<Character> java.util.stream.IntStream.mapToObj(IntFunction<? extends Character> mapper)

If i remove it, I get the following error

The method mapToInt((<no type> c) -> {}) is undefined for the type IntStream

Can someone explain this? It seems like I am starting with and IntStream, converting to a Stream of Characters and then back to IntStream.

like image 260
mancocapac Avatar asked Jun 10 '19 22:06

mancocapac


1 Answers

The method CharSequence::chars returns the IntStream, which of course doesn't provide any method converting to int, such as mapToInt, but mapToObj instead. Therefore the method IntStream::map(IntUnaryOperator mapper) which both takes returns int as well shall be used since IntUnaryOperator does the same like Function<Integer, Integer> or UnaryOperator<Integer>:

int count = myString.chars()                 // IntStream
    .map(c -> (set.add((char) c) ? 1 : 0))   // IntStream
    .sum();

long count = myString.chars()                // IntStream
    .filter(c -> set.add((char) c))          // IntStream
    .count();

Also, using Set<Integer> helps you to avoid conversion to a Character:

Set<Integer> set = new HashSet<>();

int count = myString.chars()                 // IntStream
    .map(c -> (set.add(c) ? 1 : 0))          // IntStream
    .sum();

long count = myString.chars()                // IntStream
    .filter(set::add)                        // IntStream
    .count();

However, regardless of what you try to achieve, your code is wrong by principle. See the Stateless behaviors. Consider using the following snippet which lambda expressions' results are not dependent on the result of a non-deterministic operation, such as Set::add.

Stream pipeline results may be nondeterministic or incorrect if the behavioral parameters to the stream operations are stateful.

long count = myString.chars()             // IntStream
                     .distinct()          // IntStream
                     .count();
like image 198
Nikolas Charalambidis Avatar answered Sep 28 '22 18:09

Nikolas Charalambidis