Java Path Streams Trap

Categories: Java

Java1.8 streams and closures can be cool:

  return Files.list(baseDir)
            .filter(path -> path.getFileName().toString().endsWith(suffix))
            .collect(Collectors.toList());

However there is a nasty bug in the above: Files.list(baseDir) returns a stream object that must be explicitly closed. Not doing so leaks a file-handle to the directory being listed! Sadly, the bugfree version does not look quite so elegant:

  try(Stream<Path> paths = Files.list(baseDir)) {
    return paths
            .filter(path -> path.getFileName().toString().endsWith(suffix))
            .collect(Collectors.toList());
  }

And by the way, the “toString” is necessary too, as Path.endsWith() and String.endsWith() are not the same thing.

Designing good library APIs is an art - and IMO whoever at Sun approved Files.list and Path.endsWith screwed up. If only they had read Chapter 5, “Candy Machine Interfaces” from “Writing Solid Code” by Steve Maguire - an old book now, but that chapter has some great and still-relevant advice.