Working on a project I encountered a situation which I do not know how to properly solve. I am not sure if my solution is the best I could use. But let me introduce the problem (I reproduced it as simply as I could).
There is a class (which is not properly written) which simply gets filenames from directory:
public class StreamTest
{
public List<String> getList(Path dir) {
return getStream(dir)
.map(filename -> filename.toString())
.collect(Collectors.toList());
}
private Stream<Path> getStream(Path dir)
{
if (Files.exists(dir)) {
try {
Stream<Path> stream = Files.walk(dir, 1);
return stream
.filter(Files::isRegularFile)
.map(dir::relativize);
} catch (IOException e) {
System.out.println("Error");
}
}
return null;
}
}
and Main.class
public class Main {
public static void main(String[] args) {
Path dir = Paths.get("C:\\Projects\\Tests\\Walk");
StreamTest streamTest = new StreamTest();
List<String> list = streamTest.getList(dir);
System.out.println(list);
}
}
It works but you see what's wrong? Files.walk(dir, 1)
should be run with try-with-resources.
But when I replace:
try {
Stream<Path> stream = Files.walk(dir, 1);
with
try (Stream<Path> stream = Files.walk(dir, 1)) {
I receive IllegalStateException
.
And now question:
Is this approach correct at all? I mean getting stream from method and working on it? But how to properly use try-with-resources in that situation?
The workaround is to return List of some mapped type (e.g String
) instead of Stream
from getStream
and work with it in getList method but I am curious if there is good answer to the question asked.
Certainly I may do all job in one method but hypothetically I may call getStream
from couple of other methods.
I receive IllegalStateException.
That's because you've closed the stream before you try to access anything from it. A try-with-resources in the getStream
method will close the stream when that method returns; so you won't be able to read the stream in getList
.
Put the try-with-resources in getList
:
public List<String> getList(Path dir) {
try (Stream<Path> stream = getStream(dir)) {
return stream
.map(filename -> filename.toString())
.collect(Collectors.toList());
}
}