0

I have solved the problems from the Java book, and I have some questions.

In the code below, I want to create a new stream by doubling each element using the map intermediate operation. And I want to print a new stream to get the sum of all the elements except the number less than 50 in the generated stream.

How can i solve this ??

    package test;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;
import java.util.Optional;
import java.util.stream.IntStream;

public class tt {


public static void main(String[] args) {
    try {
        Stream <String> lines = Files.lines(Paths.get("C:\\Users\\wonheelee\\eclipse-workspace\\test\\stream-data.txt"));


        IntStream IS = lines.mapToInt(Integer::valueOf);

        IS.forEach(System.out::println);
        lines.close();

    } catch (IOException e) {
       // No action 
    }
}
}
Ousmane D.
  • 54,915
  • 8
  • 91
  • 126
Won Hee Lee
  • 65
  • 2
  • 9

1 Answers1

2

Here you go..

int result = lines
            .mapToInt(Integer::parseInt)
            .map(element -> element * 2) //Double
            .filter(element -> element >= 50) //Filter out values less than 50
            .sum(); //sum

You can combine the mapToInt and map in one mapToInt itself

.mapToInt(element -> Integer.parseInt(element) * 2)

Also, note as Aomine@ mentioned in the comments, using Integer.parseInt to avoid an extra boxing/unboxing.


I'm not quite sure what you mean by create a new stream. You can get a new Stream by calling Files.lines again.

You cannot reuse a Stream once it is already consumed.

Reference:

Is there any way to reuse a Stream?

davidxxx
  • 125,838
  • 23
  • 214
  • 215
Thiyagu
  • 17,362
  • 5
  • 42
  • 79
  • Just for better readabilty I would first run the `filter` and then the mapping function to double the integer in question. – akortex Jul 30 '18 at 16:59
  • 1
    @Aris you can't filter them without doubling it. anyhow i'd change `.mapToInt(Integer::valueOf)` to `.mapToInt(Integer::parseInt)` to avoid boxing and unboxing the value. – Ousmane D. Jul 30 '18 at 17:00
  • Of course you can do that. You need to first map them to an int `mapToInt` filter the mapped and transformed integer and then map that again using a doubling action, before finally applying the `sum` terminal operation. – akortex Jul 30 '18 at 17:02
  • @Aris unless I am missing something, the only case where you can `filter` first then `map` and still suffice is `lines .mapToInt(Integer::parseInt) .filter(a -> a * 2 >= 50) .map(a -> a * 2) .sum();` which is not what you're saying. but i'd avoid that and just do `ines.mapToInt(Integer::parseInt) .map(i -> i * 2).filter(i -> i >= 50) .sum();` – Ousmane D. Jul 30 '18 at 17:07
  • @Aomine that is exactly what I'm referring to (the last line of code). – akortex Jul 30 '18 at 17:08
  • 1
    @Aris My understanding is that the OP wants to double first and then filter. If you filter first, then you won't get number say for ex, 26. – Thiyagu Jul 30 '18 at 17:09
  • @Aomine it's very trivial but I understood that they first want to map and filter and then apply the doubling action. – akortex Jul 30 '18 at 17:11
  • 2
    @Aomine for the smart people: `.mapToInt(Integer::parseInt).filter(a -> a >= 25).sum()*2` ;-) – Holger Jul 30 '18 at 18:47
  • @Holger oh my..... that's too smart! , no many people would think of that approach. – Ousmane D. Jul 30 '18 at 18:54
  • @Holger I have to admit, I had to _double_ check this on [ideone](https://ideone.com/T9Gbi7) to make sure what my brain is processing is correct. – Ousmane D. Jul 30 '18 at 19:24
  • @Holger Nice one – Thiyagu Jul 31 '18 at 03:55
  • @Aomine It is - `2*a + 2*b + 2*c ..` which is `2 * (a + b + c)` – Thiyagu Jul 31 '18 at 03:55