Arthur
Arthur

Reputation: 1176

How stream search, based on previous filter results, can be simplified?

How stream search, based on previous filter results, can be simplified ?

   HashMap<Boolean, List<Path>> result = (HashMap<Boolean, List<Path>>) Files.walk(Paths.get(folder)).map(Path
            ::toAbsolutePath).collect(Collectors.groupingBy(Files::isSymbolicLink));
    result.get(true).stream().filter(path -> {
        try {
            return !result.get(false).contains(Files.readSymbolicLink(path));
        } catch (IOException e) {
            throw Throwables.propagate(e);
        }
    }).forEach(symbolicLink -> {
        try {
            result.get(false).addAll(Files.walk(symbolicLink, FileVisitOption.FOLLOW_LINKS).collect(Collectors
                    .toList()));
        } catch (IOException e) {
            throw Throwables.propagate(e);
        }
    });

    return result.get(false).stream().filter(Files::isRegularFile).distinct().collect(Collectors.toList());

Upvotes: 0

Views: 69

Answers (1)

explv
explv

Reputation: 2759

You could tidy it up by extracting some of the code into methods, and by avoiding using a HashMap.

Instead of a HashMap you can store the files in a Set<Path>. This enforces uniqueness, so you don't really need to bother checking if the symbolic link leads to a file you already have, and you can remove some of the filtering:

public Set<Path> getAllFiles(final String folder) throws IOException {
    return Files.walk(Paths.get(folder))
            .map(Path::toAbsolutePath)
            .flatMap(this::getAllFiles)
            .collect(Collectors.toSet());
}

private Stream<Path> getAllFiles(final Path path) {
    if(!Files.isSymbolicLink(path)) return Stream.of(path);
    try {
        return Files.walk(path, FileVisitOption.FOLLOW_LINKS)
                .filter(Files::isRegularFile);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return Stream.empty();
}

Upvotes: 1

Related Questions