How to turn a number reading directly into stream?

3

Recently I wrote a response by exploring Java's stream API a bit more, but I should say that I was disappointed with some details of my code.

The idea was to read a sequence of numbers and then return the highest and lowest value of the readings performed. In this case, the entry ended when the number 0 was entered.

I do not know how to skilfully use an iterable with the stream APIs. So I decided to go by the pig method and purpose: I know how to read data and play in ArrayList to then use this list quietly to stream . The resulting code was this:

Scanner input = new Scanner(System.in); 
ArrayList<Double> lista = new ArrayList<>();

double valorLido;
while (true) {
  valorLido = input.nextDouble();
  if (valorLido == 0) {
    break;
  }
  lista.add(valorLido);
}
DoubleSummaryStatistics summary = lista.stream().collect(Collectors.summarizingDouble(Double::doubleValue));
double maior = summary.getMax();
double menor = summary.getMin();
System.out.println("maior " + maior);
System.out.println("menor " + menor);

This code did not please me. I would like to be able to directly use the result of the reading to go to stream without needing to transform into any type of collection.

For example, if I were to get an iterable read from the readings, it would look like this:

Iterable<Double> leitorDoubleAteh0(Scanner in) {
  return () -> new Iterator<Double>() {
    boolean conseguiuFetch;
    double valorFetch;
    void fetchNext() {
        valorFetch = in.nextDouble();
        conseguiuFetch = valorFetch != 0;
    }

    @Override
    public boolean hasNext() {
      return conseguiuFetch;
    }

    @Override
    public Double next() {
      if (!conseguiuFetch) {
        throw new NoSuchElementException("fim da leitura");
      }
      double valorRetorno = valorFetch;
      fetchNext();
      return valorRetorno;
    }

    {
      fetchNext();
    }
  };
}

This would at least give me access to foreach , but it's still not my desired stream .

    
asked by anonymous 27.03.2018 / 04:36

1 answer

2

With method Stream.generate(Supplier<? extends T>) , you can read the numbers of Scanner without needing ArrayList .

I know the tag is . But if you agree to use Java 9 or higher, you can use method Stream.takeWhile(Predicate<? super T>) to make the stop criterion.

Here's the result:

Scanner input = new Scanner(System.in);
DoubleSummaryStatistics summary = Stream
        .generate(input::nextDouble)
        .takeWhile(z -> z != 0)
        .collect(Collectors.summarizingDouble(Double::doubleValue));
double maior = summary.getMax();
double menor = summary.getMin();
System.out.println("maior " + maior);
System.out.println("menor " + menor);
    
28.03.2018 / 22:45