-1

I was trying to run this example code (Horstmann's Java for the Impatient) which tries to find the frequency of occurrence of words in all files under a directory tree path.

It looks for regular files but does not exclude executables and binary files including .class files.

So I wanted to add a filter to exclude .class and non-text files.

.filter(!Files::isExecutable)

over here:

return entries.filter(Files::isRegularFile).filter(!Files::isExecutable).collect(Collectors.toSet());

But that will not compile. Hence I was wondering - how can one combine a boolean operator with a method reference?

package ch10.sec05 ;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class CHMDemo {
    public static ConcurrentHashMap<String, Long> map = new ConcurrentHashMap<>();

    public static void process(Path path) {
        try {
            String contents = Files.readString(path);
            for (String word : contents.split("\\PL+")) {
                map.merge(word, 1L, Long::sum);
            }
        } catch (IOException ex) {
            System.err.println("path:" + path);;
            ex.printStackTrace();
        }
    }
    
    public static Set<Path> descendants(Path p) throws IOException {        
        try (Stream<Path> entries = Files.walk(p)) {
            return entries.filter(Files::isRegularFile).collect(Collectors.toSet());
        }
    }
    
    public static void main(String[] args) throws InterruptedException, ExecutionException, IOException {
        int processors = Runtime.getRuntime().availableProcessors();
        ExecutorService executor = Executors.newFixedThreadPool(processors);
        Path pathToRoot = Paths.get("..");
        for (Path p : descendants(pathToRoot)) {
            executor.execute(() -> process(p));
        }        
        executor.shutdown();
        executor.awaitTermination(10, TimeUnit.MINUTES);
        System.out.println(map);
    }
}

Update:

I tried

return entries.filter(Files::isRegularFile).filter(((Predicate<? super Path>) Files::isExecutable).negate()).collect(Collectors.toSet());

but that returns no output at all.

likejudo
  • 2,946
  • 6
  • 45
  • 90

0 Answers0