好的,我最终实现了自己的迭代器来执行此操作(正如 Amir 建议的那样)。这不是微不足道的(尽管幸运的是有人已经编写了代码来扁平化迭代器),但相当简单
它仍然在内存中保存单个目录(没有后代)的完整列表,因此对于平面目录布局没有用(在这种情况下,我认为在 Java 7 之前使用纯 Java 是不走运的)但到目前为止它正在工作对我的用例来说好多了。
RecursiveFileIterable.java
:
import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public class RecursiveFileIterable implements Iterable<File> {
private File file;
public RecursiveFileIterable(File f) {
file = f;
}
public RecursiveFileIterable(String filename) {
this(new File(filename));
}
private class DirectoriesOnlyFilter implements FileFilter {
@Override
public boolean accept(File pathname) {
return pathname.isDirectory();
}
}
private class NoDirectoriesFilter implements FileFilter {
@Override
public boolean accept(File pathname) {
return !pathname.isDirectory();
}
}
@Override
public Iterator<File> iterator() {
List<File> normFiles = Arrays.asList(file
.listFiles(new NoDirectoriesFilter()));
ArrayList<Iterable<File>> pendingIterables = new ArrayList<Iterable<File>>();
pendingIterables.add(normFiles);
File[] subdirs = file.listFiles(new DirectoriesOnlyFilter());
for (File sd : subdirs)
pendingIterables.add(new RecursiveFileIterable(sd));
return new FlattenIterable<File>(pendingIterables).iterator();
}
}
FlattenIterable.java
:
// from http://langexplr.blogspot.com.au/2007/12/combining-iterators-in-java.html
import java.util.Iterator;
public class FlattenIterable<T> implements Iterable<T> {
private Iterable<Iterable<T>> iterable;
public FlattenIterable(Iterable<Iterable<T>> iterable) {
this.iterable = iterable;
}
public Iterator<T> iterator() {
return new FlattenIterator<T>(iterable.iterator());
}
static class FlattenIterator<T> implements Iterator<T> {
private Iterator<Iterable<T>> iterator;
private Iterator<T> currentIterator;
public FlattenIterator(Iterator<Iterable<T>> iterator) {
this.iterator = iterator;
currentIterator = null;
}
public boolean hasNext() {
boolean hasNext = true;
if (currentIterator == null) {
if (iterator.hasNext()) {
currentIterator = iterator.next().iterator();
} else {
return false;
}
}
while (!currentIterator.hasNext() && iterator.hasNext()) {
currentIterator = iterator.next().iterator();
}
return currentIterator.hasNext();
}
public T next() {
return currentIterator.next();
}
public void remove() {
}
}
}