首页 > 解决方案 > 执行集合操作时,是否可以修改底层集合?

问题描述

例如,我有以下代码递归复制目录的内容。

    private fun copyContentDirectory(directory : File): List<File> {
        val files = directory.listFiles().toList()
        val filesToTransform = mutableListOf<File>()

        // Add each file + directory. Then, recursively add the files in each directory.
        files
                .onEach  { filesToTransform += it }
                .filter  { it.isDirectory }
                .forEach { filesToTransform += copyContentDirectory(it) }

        return filesToTransform
    }

是否有可能有类似以下的东西?如果不是,为什么不呢?


    private fun copyContentDirectory(directory : File): List<File> {
        return directory.listFiles().toList()
                .filter  { it.isDirectory }
                .onEach  { <thisList> += copyContentDirectory(it) }
    }

thisList允许我引用基础列表的符号在哪里。这样的事情存在吗?

标签: kotlincollections

解决方案


根据评论,您的意图不是很清楚。

看第二个例子,显而易见的答案似乎是替换这一行:

.onEach { <thisList> += copyContentDirectory(it) }

一个使用flatMap(),例如:

.flatMap{ copyContentDirectory(it) }

这将所有递归调用的结果收集在一起,并将它们作为一个列表返回——我认为这就是你想要的。

然而,这只揭示了更深层次的问题:

  • 尽管有这个名字,但该方法实际上并没有复制任何东西,只是收集了一个列表。
  • 该列表将始终为空 - 它在目录上递归,但从不返回任何文件,因此只会组合空列表。

这是解决第二个问题的版本。我还对其进行了重命名,将其重铸为扩展函数,并用于partition()避免过滤两次。(第一个结果是与谓词匹配的文件,即目录,它在其上递归;第二个结果是不匹配的文件,即非目录,它直接包含。)并且因为listFiles()在某些情况下可以返回 null,它必须处理那个也是。

private fun File.listContents(): List<File>
    = listFiles()
        ?.partition{ it.isDirectory }
        ?.let{ it.first.flatMap{ it.listContents() } + it.second }
        ?: listOf()

(这并没有解决复制问题,但问题并未表明您打算如何处理。)


推荐阅读