I like new Java8 StreamAPI and want use it not only for one file. As usually, I use this code:
Stream lines = Files.lines(Paths.get(\"/somepat
You can use following code
Files.list(Paths.get("path"))
.filter(Files::isRegularFile)
.flatMap(s -> {
try {
return Files.lines(s);
} catch (IOException e) {
e.printStackTrace();
}
return null;
})
.forEach(System.out::println);
Without any extra helper functions or outside libraries, the easiest is:
Stream<String> lines1 = Files.lines(Paths.get("/somepathtofile"));
Stream<String> lines2 = Files.lines(Paths.get("/somepathtoanotherfile"));
Stream.concat(lines1, lines)
.filter(...)
.forEach(...);
If Files.lines
hadn't been declared to throw a checked exception, you'd be able to do
Stream.of("/file1", "/file2")
.map(Paths::get)
.flatMap(Files::lines)....
But, alas, we can't do that. There are several workarounds. One is to make your own version of Files.lines
that calls the standard one, catches IOException
and rethrows as an UncheckedIOException
. Another approach is a more general way to make functions out of methods that throw checked exceptions. It would look something like this:
@FunctionalInterface
public interface ThrowingFunction<T,R> extends Function<T,R> {
@Override
public default R apply(T t) {
try {
return throwingApply(t);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static<T,R> Function<T,R> wrap(ThrowingFunction<T,R> f) {
return f;
}
R throwingApply(T t) throws Exception;
}
and then
Stream.of("/somefile", "/someotherfile", "/yetanotherfile")
.map(Paths::get)
.flatMap(ThrowingFunction.wrap(Files::lines))
.....
There are several libraries out there that went through the trouble of writing something like the above out for every functional interface.
With cyclops-streams (a library we have created) you can write
SequenceM.of("/somepathtofile1","/somepathtofile2")
.flatMapFile(File::new)
.forEach(System.out::println);
Javadoc SequenceM extends java.util.stream.Stream (and also org.jooq.lambda.Seq) to add a lot of additional convenience methods.