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

生成无重复5行数字组合遇内存错误,求优化方案

解决5行无重复数字组合生成的内存溢出问题

问题背景

需要生成0-100范围内无重复数字的5行组合(例如1,2,3,4,5、1,2,3,4,6这类所有可能的组合)。当仅生成3行组合时功能正常,但添加第4、5行后,因组合总量达到约1200万条,出现内存错误。核心问题是一次性加载所有组合导致内存耗尽,而非代码逻辑错误,需要通过分批生成/懒加载的方式优化。

原代码问题分析

原代码存在两个关键问题:

  1. 内存占用过高:通过嵌套flatMap+map直接生成所有组合并转换为List,1200万条字符串会一次性存入内存,远超移动端应用的内存上限。
  2. 代码冗余:手动定义rowOne到rowFive的字符串列表,重复且易出错;同时未做重复数字过滤,可能生成包含重复数字的组合(例如2,2,3,4,5这类不符合需求的结果)。

原代码如下:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val startButton = findViewById<Button>(R.id.startButton)
        val possibilities = findViewById<TextView>(R.id.possibilities)

        val rowOne  = listOf("1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","43","44","45","46","47","48","49","50","51","52","53","54","55","56","57","58","59","60","61","62","63","64","65","66","67","68","69","70")
        val rowTwo  = listOf("2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","43","44","45","46","47","48","49","50","51","52","53","54","55","56","57","58","59","60","61","62","63","64","65","66","67","68","69","70")
        val rowThree = listOf("3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","43","44","45","46","47","48","49","50","51","52","53","54","55","56","57","58","59","60","61","62","63","64","65","66","67","68","69","70")
        val rowFour = listOf("4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","43","44","45","46","47","48","49","50","51","52","53","54","55","56","57","58","59","60","61","62","63","64","65","66","67","68","69","70")
        val rowFive = listOf("5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","43","44","45","46","47","48","49","50","51","52","53","54","55","56","57","58","59","60","61","62","63","64","65","66","67","68","69","70")

        val combinations =
            rowOne.flatMap { rowOne ->
                rowTwo.flatMap { rowTwo ->
                    rowThree.flatMap { rowThree ->
                        rowFour.flatMap { rowFour ->
                            rowFive.map { rowFive -> "$rowFour $rowFive" }
                        }.map { resultThree -> "$resultThree $rowThree" }
                    }.map { resultTwo -> "$resultTwo $rowTwo" }
                }.map { resultOne -> "$resultOne $rowOne" }
            }.toList()

        startButton.setOnClickListener {
            possibilities.text = ("${(combinations).size} Possibilities")}
    }
}

优化方案

1. 用Sequence实现懒加载

Kotlin的Sequence是懒加载的集合,不会一次性计算所有元素,而是按需生成,能大幅降低内存占用。将原代码中的List操作替换为Sequence,避免一次性加载所有组合。

2. 过滤重复数字

通过强制后续数字大于前一个数字的方式,确保组合内无重复数字(例如r2 > r1、r3 > r2等),同时简化行的生成逻辑。

3. 分批处理组合

如果需要对组合进行存储/展示,可按固定批次处理(例如每10000条为一批),处理完成后立即释放该批次内存,避免累积占用。

优化后的代码

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val startButton = findViewById<Button>(R.id.startButton)
        val possibilities = findViewById<TextView>(R.id.possibilities)

        // 生成数字范围的字符串列表,替代手动定义
        val numRange = 1..70
        val numStrings = numRange.map { it.toString() }

        // 用Sequence生成无重复的5行组合,懒加载
        val combinationsSequence = numStrings.asSequence().flatMap { r1 ->
            // 过滤出比r1大的数字,避免重复
            numStrings.filter { it > r1 }.asSequence().flatMap { r2 ->
                numStrings.filter { it > r2 }.asSequence().flatMap { r3 ->
                    numStrings.filter { it > r3 }.asSequence().flatMap { r4 ->
                        numStrings.filter { it > r4 }.asSequence().map { r5 ->
                            "$r1 $r2 $r3 $r4 $r5"
                        }
                    }
                }
            }
        }

        startButton.setOnClickListener {
            // 计算总组合数,无需生成所有元素
            val totalCount = combinationsSequence.count()
            possibilities.text = "$totalCount Possibilities"

            // 可选:分批处理组合(示例:每10000条处理一次)
            val batchSize = 10000
            var currentBatch = mutableListOf<String>()
            combinationsSequence.forEachIndexed { index, combo ->
                currentBatch.add(combo)
                if ((index + 1) % batchSize == 0) {
                    // 这里替换为你的业务逻辑,比如写入文件、展示等
                    processBatch(currentBatch)
                    currentBatch.clear()
                }
            }
            // 处理剩余的不足一批的组合
            if (currentBatch.isNotEmpty()) {
                processBatch(currentBatch)
            }
        }
    }

    // 自定义批次处理逻辑
    private fun processBatch(batch: List<String>) {
        // 示例:打印批次大小,实际可替换为写入文件等操作
        Log.d("CombinationBatch", "Processed ${batch.size} combinations")
    }
}

关键优化点说明

  • 懒加载:asSequence()将集合转换为序列,所有flatMap、filter、map操作都不会立即执行,直到调用count()或forEach()时才按需生成元素。
  • 内存控制:分批处理时,每批处理完成后立即清空列表,释放内存,避免1200万条数据同时占用内存。
  • 代码简化:用numRange生成数字字符串列表,替代手动重复定义,减少冗余代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 00:18:19