OK, I finished implementing my own iterator to do this (as Amir suggested). It wasnβt quite trivial (although, fortunately, someone already wrote the code to smooth iterators ), but itβs quite simple
It still contains a complete list of one directory (without descendants) in memory, so it is not suitable for a flat layout of the directory (in this case, I think you're out of luck using pure Java before Java 7), but it works so far better for my use.
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() { } } }
source share