在做项目的过程中,我遇到了一个不知道如何正确解决的情况。我不确定我的解决方案是否是我可以使用的最佳解决方案。但让我介绍一下问题(我尽可能简单地重现了它)。
有一个类(未正确编写),它只是从目录中获取文件名:
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;
}
}
和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);
}
}
它可以工作,但你看到出了什么问题吗? Files.walk(dir, 1) 应该与 try-with-resources 一起运行。
但是当我更换时:
try {
Stream<Path> stream = Files.walk(dir, 1);
与
try (Stream<Path> stream = Files.walk(dir, 1)) {
我收到 IllegalStateException。
现在问题:
这种方法到底正确吗?我的意思是从方法中获取流并对其进行处理?但在这种情况下如何正确使用 try-with-resources 呢?
解决方法是从 getStream 返回某种映射类型(例如 String)的列表而不是 Stream 并在 getList 方法中使用它,但我很好奇所提出的问题是否有好的答案。
当然,我可以用一种方法完成所有工作,但假设我可以从其他几种方法调用 getStream。
我收到 IllegalStateException。
那是因为您在尝试从中访问任何内容之前已经关闭了流。
getStream
方法中的 try-with-resources 将在该方法返回时关闭流;所以你将无法读取getList
中的流。
将 try-with-resources 放入
getList
:
public List<String> getList(Path dir) {
try (Stream<Path> stream = getStream(dir)) {
return stream
.map(filename -> filename.toString())
.collect(Collectors.toList());
}
}
如果您不使用单独的 getStream() 方法,则可以对资源使用 try :
public List<String> getList(Path dir) {
if ( Files.exists(dir)) {
try (Stream<Path> stream = Files.walk(dir, 1)) {
return stream
.filter(Files::isRegularFile)
.map(dir::relativize).map(filename -> filename.toString())
.collect(Collectors.toList());
} catch ( IOException ioe) {
System.out.println("ERROR: " + ioe.getMessage());
}
}
return null;
}
try-with-resources 块完成后,try-with 资源就会关闭 Stream,这会导致您的问题。
在上面的示例中,所有内容都保留在 try-with-resources 块内,因此 Stream 仍然可以用于查找所需的 List。