1

I am new to Java and trying out Streams for the first time.

I have a large input file where there is a string on each line like:

cart
dumpster
apple
cherry
tank
laptop
...

I'm trying to read the file in as a Stream and doing some analysis on the data. For example, to count all the occurrences of a particular string, I might think to do something like:

Stream<String> lines = Files.lines(Path.of("/path/to/input/file.txt"));
int count = 0;

lines.forEach((line) => {
    if (line.equals("tank")) {
        count++;
    }
});

But, Java doesn't allow mutation of variables within the lambda.

I'm not sure if there's another way to read from the stream line by line. How would I do this properly?

Sujay Mohan
  • 933
  • 7
  • 14
noblerare
  • 10,277
  • 23
  • 78
  • 140
  • 2
    Not an answer but take a look at [this post](https://stackoverflow.com/questions/513832/how-do-i-compare-strings-in-java) to learn about comparing strings. – stdunbar Dec 01 '21 at 16:58
  • 1
    In general, instead of just using Stream for simple iteration, make use of its method as `map`, `flatMap`, `filter`, `collect`, `reduce`. They are super powerful. `forEach` ideally should be used only if you want to execute some action on each element. – Mirek Pluta Dec 01 '21 at 17:05

3 Answers3

5

You don't need a variable external to the stream. And if you have a really big file to count, long would be preferred

long tanks = lines
    .filter(s -> s.equals("tank"))
    .count();
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
4

To iterate a stream using a regular loop, you can get an iterator from your stream and use a for-loop:

Iterable<String> iterable = lines::iterator;
for (String line : iterable) {
    if (line.equals("tank")) {
         ++count;
    }
}

But in this particular case, you could just use the stream's count method:

int count = (int) lines.filter("tank"::equals).count();
khelwood
  • 55,782
  • 14
  • 81
  • 108
  • Thanks. This answer actually helped me solve my real issue which wasn't just about counting occurrences but showing me how to iterate over the stream without using a lambda in`forEach` – noblerare Dec 01 '21 at 19:09
  • 1
    Well, if you don’t use the benefits of the Stream API, don’t use a Stream in the first place. To iterate over the lines of a file, you can use a `BufferedReader` or a `Scanner`. – Holger Dec 03 '21 at 09:34
0

you can read from the file line by line, with stream of each one :

    try (Stream<String> lines = Files.lines(Path.of("/path/to/input/file.txt"))) {
        list = stream
                .filter(line -> !line.startsWith("abc"))
                .map(String::toUpperCase)
                .collect(Collectors.toList());

    } catch (IOException e) {
        e.printStackTrace();
    }
tchiko
  • 56
  • 6