有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

在java中列出在arraylist中收集数据的更快方法

我有一个包含许多文件的目录,希望筛选具有特定名称的目录,并将它们保存在fileListArrayList中,它以这种方式工作,但需要花费很多时间。有没有办法让这更快

String processingDir = "C:/Users/Ferid/Desktop/20181024";
String CorrId = "00a3d321-171c-484a-ad7c-74e22ffa3625");
Path dirPath = Paths.get(processingDir);       

ArrayList<Path> fileList;

try (Stream<Path> paths = Files.walk(dirPath))
{           
    fileList = paths.filter(t -> (t.getFileName().toString().indexOf("EPX_" + 
    corrId + "_") >= 0)).collect(Collectors.toCollection(ArrayList::new));
}

在try条件下遍历目录不会花费太多时间,但是在fileList中收集目录会花费太多时间,我不知道它到底是哪个操作,哪个操作的性能较差,或者需要改进哪个操作。(这当然不是完整的代码,只是相关的东西)


共 (2) 个答案

  1. # 1 楼答案

    java.nio.file.Files.walk(Path)api:

    Return a Stream that is lazily populated with Path by walking the file tree rooted at a given starting file.

    这就是为什么它给您的印象是“在try条件下遍历目录不会花费太多时间”

    事实上,真正的交易大多是在collect上完成的,这不是collect的机制错误,因为它速度慢

  2. # 2 楼答案

    如果每次扫描文件的速度太慢,可以在启动时建立文件索引,也可以在文件更改时进行持久化和维护

    您可以使用Watch Service在程序运行时添加或删除文件时收到通知

    这将大大加快查询速度,因为它将完全位于内存中。第一次加载需要相同的时间,但可能是在您最初需要它之前加载背景

    例如

    static Map<String, List<Path>> pathMap;
    public static void initPathMap(String processingDir) throws IOException {
        try (Stream<Path> paths = Files.walk(Paths.get(processingDir))) {
            pathMap = paths.collect(Collectors.groupingBy(
                    p -> getCorrId(p.getFileName().toString())));
        }
        pathMap.remove(""); // remove entries without a corrId.
    }
    
    
    private static String getCorrId(String fileName) {
        int start = fileName.indexOf("EPX_");
        if (start < 0)
            return "";
        int end = fileName.indexOf("_", start + 4);
        if (end < 0)
            return "";
        return fileName.substring(start + 4, end);
    }
    
    // later 
        String corrId = "00a3d321-171c-484a-ad7c-74e22ffa3625";
        List<Path> pathList = pathMap.get(corrId); // very fast.
    

    您可以通过编写以下代码使代码更干净,但是,我不希望它更快

    List<Path> fileList;
    
    try (Stream<Path> paths = Files.walk(dirPath)) {           
        String find = "EPX_" + corrId + "_"; // only calculate this once
        fileList = paths.filter(t -> t.getFileName().contains(find))
                        .collect(Collectors.toList());
    }
    

    成本是扫描目录中的文件所花费的时间。处理文件名的成本要少得多

    使用SSD,或者只扫描已经缓存在内存中的目录,将大大加快速度

    测试这一点的一种方法是在干净引导后多次执行该操作(因此不会缓存)。第一次运行花费的时间越长,说明从磁盘加载数据花费了多少时间