1

Im trying to understand streams right now. I'd like to save the highest number from a stream as an Optional, but the program only allows me to save it as an Integer. Since it's possible that the stream is empty, so there is not highest value, i'd like to be able to save it as an Optional.

I've tried this so far:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Optional;
import java.util.stream.Stream;

public class StreamsTest {

    public static void main(String[] args) {

        Collection<Integer> list = new ArrayList<Integer>();
        for (int i = 0; i < 10; i++) {
            list.add(i);
        }
        Stream<Integer> stream1 = list.stream().filter(x -> x % 2 == 1);
        if (stream1.findAny().isPresent() == true)
            System.out.println("Hey");
        Optional<Integer> opt = stream1.max(Comparator.comparing(Integer::valueOf)).get();
    }

}

Is it because of the .get()? I could imagine that when i use it, the program expects to get a value. If it doesnt get a value it already crashes at this point and there is no need to try to save it to a variable. So it either gets a value and saves it in an Integer variable or it crashes since .get() cant deliver the input for an Optional.

Naman
  • 27,789
  • 26
  • 218
  • 353
Ikaros97
  • 37
  • 6
  • 1
    Yes, what is your question? Use get and store it as int (and maybe crash) or dont get and store it as an optional. – luk2302 Apr 30 '20 at 11:12
  • 2
    just a comment: if (stream1.findAny().isPresent() == true) can be rewritten as: if (stream1.findAny().isPresent() ) – Stultuske Apr 30 '20 at 11:12

1 Answers1

4

get returns the value itself, it unwraps the Optional, so the variable type must be Integer.

Integer opt = stream1.max(Comparator.comparing(Integer::valueOf)).get();

Note that get without isPresent is unsafe and may result in an exception.

There is a nicer way, though

int max = list.stream()
        .filter(x -> x % 2 == 1)
        .mapToInt(Integer::valueOf)
        .max()
        .orElse(0); // or other value

This check

if (stream1.findAny().isPresent() == true)
    System.out.println("Hey");

is not proper since it's always going to be true (1) [judging from your input] and uses the terminal operation on the stream (2) [meaning you can't reuse it later on as you were trying to].

The whole method could be rewritten to

IntStream
        .range(0, 10)
        .filter(x -> x % 2 == 1)
        .max()
        .orElseThrow(() -> new IllegalArgumentException("no max"));

Note that I used a different technique here. I am going to throw an exception if the max can't be calculated (no elements in the stream).

Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
  • Thanks alot. So you recommend using an IntStream instead of a stream? Like IntStream stream = new IntStream(); stream.range(0,10) etc. ? And why should i use range? Can i just use max() without any parameters? Lets say my filter was x -> x % 2 == 155. Then my stream would be empty after i filtered it. Would my findAny.isPresent still be true? – Ikaros97 Apr 30 '20 at 12:35
  • 1
    @Ikaros97 I just replaced your loop with the IntStream generator to show it's a possibility. – Andrew Tobilko Apr 30 '20 at 12:56
  • 1
    @Ikaros97 Both Stream and IntStream have their applications. The latter is simply a primitive version of Stream with a set of corresponding int methods – Andrew Tobilko Apr 30 '20 at 12:58