I wrote this method:
public static void main(String... args) {
try (var linesStream = Files.lines(Paths.get("C:\\Users\\paul\\Desktop\\java.txt"))) {
Stream<String> words = linesStream.
flatMap(line -> Arrays.stream(line.split(" ")))
.distinct();
System.out.println("There are " + words.count() + " distinct words in this file, here they are:");
words.forEach(System.out::println);
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
The problems I have here is that I operate on the words Stream<String> twice. In order to do that do you have to explicitly rebuild this stream, or is there some magic reset method I could use?
Also, in order to rebuild the words stream again, I have to rebuild the linesStream and wrap that into another try/catch block here... Very verbose. What is a method to make this type of things easier to write?
I guess I could do:
static Stream<String> getStreamFromFile() throws IOException {
return Files.lines(Paths.get("C:\\Users\\paul\\Desktop\\java.txt"));
}
static Stream<String> getDistinctWords(Stream<String> lines) {
return lines
.flatMap(line -> Arrays.stream(line.split(" ")))
.distinct();
}
public static void main(String... args) {
Stream<String> lines1 = null;
Stream<String> lines2 = null;
try {
lines1 = getStreamFromFile();
lines2 = getStreamFromFile();
Stream<String> distinctWords1 = getDistinctWords(lines1);
Stream<String> distinctWords2 = getDistinctWords(lines2);
System.out.println("There are " + distinctWords1.count() + " distinct words in this file, here they are:");
distinctWords2.forEach(System.out::println);
} catch (IOException e) {
System.err.println(e.getMessage());
} finally {
lines1.close();
lines2.close();
}
}
but is this all I am left with?
You can't re-use streams. Just collect the elements into a collection, e.g. a List, or call a (stateful) function which outputs each element and also increments a count.
You can't reset a Stream, but you can collect the results of your distinct(); and you can also use \\s+ as a regex. Like,
static List<String> getDistinctWords(Stream<String> lines) {
return lines.flatMap(line -> Arrays.stream(line.split("\\s+"))).distinct()
.collect(Collectors.toList());
}
And then change your caller like
List<String> distinctWords = getDistinctWords(lines);
System.out.println("There are " + distinctWords.size()
+ " distinct words in this file, here they are:");
distinctWords.forEach(System.out::println);
And you shouldn't hard code paths like that, you can use the user.home system property to locate your file. Like,
return Files.lines(Paths.get(System.getProperty("user.home"), "Desktop/java.txt"));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With