Skip to content

Instantly share code, notes, and snippets.

@fge
Created November 8, 2014 20:18
Show Gist options
  • Select an option

  • Save fge/35acf87ab7f166765540 to your computer and use it in GitHub Desktop.

Select an option

Save fge/35acf87ab7f166765540 to your computer and use it in GitHub Desktop.
package com.github.fge;
import java.io.Closeable;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public final class LazyDirectoryIterator
implements Iterator<Path>, Closeable
{
private static final int QUEUE_SIZE = 5;
private static final long TIMEOUT_QUANTITY = 100L;
private static final TimeUnit TIMEOUT_UNIT = TimeUnit.MILLISECONDS;
private final ExecutorService executor
= Executors.newSingleThreadExecutor();
private final BlockingQueue<Path> queue
= new ArrayBlockingQueue<>(QUEUE_SIZE);
private volatile Path nextPath;
private boolean needNext = true;
public LazyDirectoryIterator(final Path baseDir)
{
executor.submit(new Runnable()
{
@Override
public void run()
{
try {
Files.walkFileTree(baseDir, new CustomVisitor());
} catch (IOException ignored) {
Thread.currentThread().interrupt();
}
}
});
}
@Override
public boolean hasNext()
{
try {
if (needNext) {
nextPath = queue.poll(TIMEOUT_QUANTITY, TIMEOUT_UNIT);
needNext = false;
}
return nextPath != null;
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
return false;
}
}
@Override
public Path next()
{
if (!hasNext())
throw new NoSuchElementException();
needNext = true;
return nextPath;
}
@Override
public void remove()
{
throw new UnsupportedOperationException();
}
@Override
public void close()
throws IOException
{
executor.shutdownNow();
}
private final class CustomVisitor
extends SimpleFileVisitor<Path>
{
@Override
public FileVisitResult preVisitDirectory(final Path dir,
final BasicFileAttributes attrs)
throws IOException
{
try {
queue.put(dir);
return FileVisitResult.CONTINUE;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IOException("timeout", e);
}
}
}
public static void main(final String... args)
throws IOException
{
final Path baseDir = Paths.get("/home/fge/t");
try (
final LazyDirectoryIterator it = new LazyDirectoryIterator(baseDir)
) {
while (it.hasNext())
System.out.println(it.next());
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment