Как мне правильно настроить сортировку коллекции в Java

Есть код который ищет в папках файлы нужного размера. Все работало нормально, но по условиям задания нужно было добавить многопоточность, ее я добавил, разделив работу тем, что один поток перебирает папку и подпапки, а второй пишет в консоль соответствующие условию файлы. Но когда он выводил сразу в консоль файлы переставала работать сортировка(нужно по убыванию размера), использовал метод - fileList.sort(Comparator.comparingLong(File::length).reversed());
Что бы он снова заработал мне посоветовали выводить ни сразу в консоль файлы, а собирать их в коллекцию , потом сортировать и печатать, я добавил сбор в коллекцию в этом методе "processFile()", но вероятно как-то криво, потому, что файлы нужные выводиться так же в консоль, но сортировка не работает, подскажите, кто знает, как сортировку настроить в моем случае.

import java.io.File;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.RecursiveTask;

public class  Main{
    static Scanner in = new Scanner(System.in);
    static File directory = new File(in.next());
    public static final double MIN_LENGTH = in.nextDouble() * 1048576;  
    static int numOfThreads = 4; // количество потоков


    public static void main(String[] args) {
        ForkJoinPool pool = new ForkJoinPool(numOfThreads);
        FileTask task = new FileTask(directory);
        pool.invoke(task);
    }

    public static class FileTask extends RecursiveAction {
        private final File file;

        public FileTask(File file) {
            this.file = file;
        }

        @Override
        protected void compute() {
            if (file.isDirectory()) {
                processDir();
            } else if (file.isFile() && file.length() > MIN_LENGTH) {
                processFile();
            }
        }

        private void processFile() {

            ArrayList<File> fileList = new ArrayList<>();
            fileList.add(file);
            fileList.sort(Comparator.<File>comparingLong(File::length).reversed());
            for(File file: fileList) {
    
            if (file.length() >= 1073741824) {
                DecimalFormat df = new DecimalFormat("#.#");
                double Gb = (double) file.length() / 1073741824;
                System.out.printf("%s Gb  %s%n", df.format(Gb), file);
            } else if (file.length() >= 1048576) {
                System.out.printf("%s Mb  %s%n", file.length() / 1048576, file);
            } else if (file.length() >= 1024) {
                System.out.printf("%s Kb  %s%n", file.length() / 1024, file);
            } else if (file.length() < 1024) {
                System.out.printf("%s B  %s%n", file.length(), file);
            } else {
                System.out.printf("%s Tb  %s%n", file.length() / (1073741824 * 1024), file);
            }
        }
    }
        private void processDir() {
            ArrayList<FileTask> tasks = new ArrayList<>();
            File[] subFiles = file.listFiles();
            for (File sub: subFiles) {
                tasks.add(new FileTask(sub));
            }
            ForkJoinTask.invokeAll(tasks);
        }
    }
}

Ответы (1 шт):

Автор решения: Nowhere Man

Вам совершенно правильно посоветовали собирать их(файлы) в коллекцию , потом сортировать и печатать, поэтому следовало для начала вынести печать из метода processFile на уровень основного класса, и также использовать RecursiveTask<List<File>>, который возвращал бы список файлов:

public static class FileTask extends RecursiveTask<List<File>> {
    private final File file;

    public FileTask(File file) {
        this.file = file;
    }

    @Override
    protected List<File> compute() {
        if (file.isDirectory()) {
            return ForkJoinTask.invokeAll(processDir())
                    .stream()
                    .map(ForkJoinTask::join)
                    .flatMap(List::stream)
                    .collect(Collectors.toList());
        } else if (file.isFile() && file.length() > minLength) {
            return processFile();
        }
        return Collections.emptyList();
    }

    private List<File> processFile() {
        return Collections.singletonList(file);
    }

    private Collection<FileTask> processDir() {
        return Arrays.stream(file.listFiles())
                .map(FileTask::new)
                .collect(Collectors.toList());
    }
}

Тогда основной функционал может выглядеть так:

public static double minLength = 1024;
public static final int NUM_OF_THREADS = 4; // количество потоков

public static void main(String[] args) {
    ForkJoinPool pool = new ForkJoinPool(NUM_OF_THREADS);
    Scanner in = new Scanner(System.in);
    System.out.print("Введите путь: ");
    File directory = new File(in.nextLine());

    System.out.print("Введите минимальный размер файла в килобайтах: ");
    minLength *= in.nextInt();

    FileTask task = new FileTask(directory);
    List<File> result = pool.invoke(task);
    result.sort(Comparator.comparingLong(File::length).reversed());
    result.forEach(Main::processFile);
}

private static void processFile(File file) {
    if (file.length() >= 1073741824) {
        DecimalFormat df = new DecimalFormat("#.#");
        double Gb = (double) file.length() / 1073741824;
        System.out.printf("%s Gb  %s%n", df.format(Gb), file);
    } else if (file.length() >= 1048576) {
        System.out.printf("%s Mb  %s%n", file.length() / 1048576, file);
    } else if (file.length() >= 1024) {
        System.out.printf("%s Kb  %s%n", file.length() / 1024, file);
    } else if (file.length() < 1024) {
        System.out.printf("%s B  %s%n", file.length(), file);
    } else {
        System.out.printf("%s Tb  %s%n", file.length() / (1073741824 * 1024), file);
    }
}
→ Ссылка