Java递归填充ArrayList数据丢失问题(规避类级列表声明)
解决递归中列表重复初始化导致数据丢失的问题
我太懂你这个痛点了——每次递归都新建列表,之前攒的数据直接就没了,但又不想把列表放到类级别(毕竟类级别的变量搞不好会有线程安全或者状态污染的麻烦)。最靠谱的解决办法就是重载方法:对外暴露的方法负责初始化列表,内部的递归方法专门用来传递这个列表并填充数据。
具体代码可以这么改:
// 对外公开的方法,不用传列表,负责初始化 private List<MyClassType> getMyClassTypes(final String path) throws SVNException { List<MyClassType> myClassTypes = new ArrayList<>(); // 调用内部递归方法,把刚初始化的列表传进去 getMyClassTypesRecursive(path, myClassTypes); return myClassTypes; } // 内部递归方法,接收已有的列表,再也不重新初始化了 private void getMyClassTypesRecursive(final String path, List<MyClassType> myClassTypes) throws SVNException { // 这里写你原来的逻辑:获取当前path下的Collection,遍历处理 Collection<?> entries = ...; // 你的SVN获取逻辑,比如svnClient.getEntries(path, ...) for (Object entry : entries) { // 如果是目录,继续递归 if (isDirectory(entry)) { // 这里替换成你判断目录的逻辑,比如entry instanceof SVNDirEntry getMyClassTypesRecursive(getEntryFullPath(entry), myClassTypes); } else { // 如果是目标文件,创建MyClassType对象并加到列表里 MyClassType type = buildMyClassTypeFromEntry(entry); // 替换成你的对象创建逻辑 myClassTypes.add(type); } } }
为什么这个方案好用?
- 对外方法只初始化一次列表,递归全程都用同一个实例,所有递归调用都会往同一个列表里加数据,再也不会丢数据了。
- 列表还是局部变量,只在对外方法的作用域里存在,完全避免了类级别变量可能带来的副作用(比如多线程调用时的并发问题)。
- 代码结构也更清晰:对外方法管入口逻辑,内部方法专注递归遍历,职责分的明明白白。
要是你不想额外写个void方法,也可以让递归方法返回列表,每次递归时把当前列表传进去再返回(不过这种写法不如void方法直观):
private List<MyClassType> getMyClassTypes(final String path) throws SVNException { return getMyClassTypesRecursive(path, new ArrayList<>()); } private List<MyClassType> getMyClassTypesRecursive(final String path, List<MyClassType> myClassTypes) throws SVNException { Collection<?> entries = ...; // 你的SVN获取逻辑 for (Object entry : entries) { if (isDirectory(entry)) { getMyClassTypesRecursive(getEntryFullPath(entry), myClassTypes); } else { myClassTypes.add(buildMyClassTypeFromEntry(entry)); } } return myClassTypes; }
两种方式都能解决你的问题,个人更推荐第一种,因为void方法能更明确地表达“我就是要修改传入的列表”这个意图,别人看代码也能一眼明白。
内容的提问来源于stack exchange,提问作者code_buddy
相关产品推荐
相关产品推荐

