You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

遍历目录时遇UnsupportedOperationException及ConcurrentModificationException问题求助

解决目录遍历中的两个异常问题

让我一步步帮你捋清楚问题根源,再给你几个可靠的实现方案:

第一个异常:UnsupportedOperationException

你一开始的代码里,Arrays.asList(dircList)返回的并不是普通的ArrayList——它是一个固定大小的List包装类,直接映射了底层数组,不支持添加/删除元素的操作。所以当你调用l.addAll(x)的时候,就会抛出这个不支持操作的异常。

哪怕你后来改成List x = new ArrayList(Arrays.asList(c.listFiles())),但外层的l还是Arrays.asList返回的固定大小列表,所以依然会报错。

第二个异常:ConcurrentModificationException

你改用Queue之后,用for (File c : l)这种foreach遍历,本质上是用队列的迭代器在遍历。而Java集合的迭代器有快速失败机制:如果在遍历过程中修改了集合的结构(比如addAll),迭代器就会检测到,直接抛出这个异常,防止出现不一致的遍历结果。


靠谱的解决方案

下面给你三种可行的实现方式,按需选择:

方案1:用while循环操作队列(最稳妥的迭代方式)

放弃foreach,改用poll()方法逐个取出队列元素,这样在循环中添加新元素就不会触发并发修改异常:

import java.io.File;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;

public static Set<File> iterateDirectory(String dir){
    Set<File> children = new HashSet<>();
    // 建议用System.getProperty获取用户目录,兼容性更好
    File dirc = new File(System.getProperty("user.home") + dir);
    File[] dircList = dirc.listFiles();
    
    // 处理目录不存在、无权限等情况,避免空指针
    if (dircList == null) {
        return children;
    }

    Queue<File> queue = new LinkedList<>(Arrays.asList(dircList));
    File currentFile;
    
    // 循环取出队列头部元素,直到队列为空
    while ((currentFile = queue.poll()) != null) {
        if(currentFile.isDirectory()){
            File[] subFiles = currentFile.listFiles();
            if (subFiles != null && subFiles.length > 0) {
                queue.addAll(Arrays.asList(subFiles));
            }
        } else {
            children.add(currentFile);
        }
    }
    return children;
}

方案2:递归遍历(代码更简洁)

如果你的目录深度不会特别大(不会触发栈溢出),递归实现会更直观:

import java.io.File;
import java.util.HashSet;
import java.util.Set;

public static Set<File> iterateDirectory(String dir){
    Set<File> children = new HashSet<>();
    File dirc = new File(System.getProperty("user.home") + dir);
    iterateDirRecursive(dirc, children);
    return children;
}

// 递归遍历子目录的私有方法
private static void iterateDirRecursive(File currentDir, Set<File> fileSet){
    File[] files = currentDir.listFiles();
    if (files == null) {
        return;
    }
    for (File file : files) {
        if (file.isDirectory()) {
            iterateDirRecursive(file, fileSet);
        } else {
            fileSet.add(file);
        }
    }
}

方案3:Java 8+的Files.walk(最简洁的标准库实现)

从Java 8开始,NIO提供了专门的文件遍历API,一行代码搞定,还自带异常处理:

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

public static Set<File> iterateDirectory(String dir){
    Path startPath = Paths.get(System.getProperty("user.home"), dir);
    try {
        return Files.walk(startPath)
                .filter(Files::isRegularFile) // 只收集普通文件
                .map(Path::toFile)
                .collect(Collectors.toSet());
    } catch (Exception e) {
        e.printStackTrace();
        return new HashSet<>();
    }
}

这个方案不仅代码最少,还能自动处理IO异常、符号链接(默认不跟随,可以通过参数调整),是Java 8+环境下的最优选择。

内容的提问来源于stack exchange,提问作者user12346306

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:36:32