Kotlin中高效构建按两狗一猫规则排列的PetsItem列表
Kotlin 高效实现 PetsItem 列表生成方案
针对你的需求,我们可以从避免低效操作、利用Sequence流式处理、减少中间对象这几个方向优化,以下是几种更高效的实现方式:
优化点说明
原代码中cats.removeAt(0)是ArrayList的O(n)操作(每次移除第一个元素需要移动后续所有元素),同时可以通过Sequence避免提前创建中间列表,进一步提升内存效率。
方案1:Sequence流式生成(无中间列表,内存友好)
通过Sequence流式处理排序、转换、插入逻辑,无需提前创建完整的DogItem列表,适合大数据量场景:
enum class CatBreed { MAINE_COON, BALINESE, BENGAL } enum class DogBreed { ITALIAN_GREYHOUND, BEAGLE, AKITA, POMERANIAN, SHIH_TZU, DACHSHUND } data class Dog(val breed: DogBreed, val order: Int) data class Cat(val breed: CatBreed) abstract class PetsItem data class DogItem(val dog: Dog) : PetsItem() data class CatItem(val cat: Cat) : PetsItem() fun main() { val dogs = listOf( Dog(DogBreed.ITALIAN_GREYHOUND, 3), Dog(DogBreed.BEAGLE, 2), Dog(DogBreed.AKITA, 1), Dog(DogBreed.POMERANIAN, 6), Dog(DogBreed.SHIH_TZU, 5), Dog(DogBreed.DACHSHUND, 4) ) val cats = listOf(Cat(CatBreed.MAINE_COON), Cat(CatBreed.BALINESE), Cat(CatBreed.BENGAL)) val petsList = dogs.asSequence() .sortedBy { it.order } .map { DogItem(it) } .withIndex() .flatMap { (index, dogItem) -> buildList { add(dogItem) // 每第2个DogItem后插入CatItem(index从0开始,所以index%2==1时触发) if (index % 2 == 1 && index / 2 < cats.size) { add(CatItem(cats[index / 2])) } } } .toList() // 输出验证 petsList.forEach { println(it) } }
优势
- 全程流式处理,无中间列表占用内存
- 用索引访问Cat,避免
removeAt(0)的O(n)开销 - 代码简洁,逻辑清晰
方案2:预初始化容量的循环实现(高效直观)
如果偏好循环写法,通过预初始化列表容量和索引访问Cat来优化:
fun main() { val dogs = listOf( Dog(DogBreed.ITALIAN_GREYHOUND, 3), Dog(DogBreed.BEAGLE, 2), Dog(DogBreed.AKITA, 1), Dog(DogBreed.POMERANIAN, 6), Dog(DogBreed.SHIH_TZU, 5), Dog(DogBreed.DACHSHUND, 4) ) val cats = listOf(Cat(CatBreed.MAINE_COON), Cat(CatBreed.BALINESE), Cat(CatBreed.BENGAL)) val orderedDogs = dogs.sortedBy { it.order } // 提前计算容量,避免ArrayList自动扩容的开销 val maxCatCount = minOf(orderedDogs.size / 2, cats.size) val petsList = ArrayList<PetsItem>(orderedDogs.size + maxCatCount) var catIndex = 0 for ((index, dog) in orderedDogs.withIndex()) { petsList.add(DogItem(dog)) if (index % 2 == 1 && catIndex < cats.size) { petsList.add(CatItem(cats[catIndex])) catIndex++ } } petsList.forEach { println(it) } }
优势
- 预初始化容量,避免多次扩容的性能损耗
- 索引访问Cat,操作是O(1),比
removeAt(0)高效数倍 - 代码直观,易理解和调试
方案3:chunked分组插入(简洁优雅)
利用Sequence的chunked方法将DogItem按每2个分组,每组后插入CatItem:
fun main() { val dogs = listOf( Dog(DogBreed.ITALIAN_GREYHOUND, 3), Dog(DogBreed.BEAGLE, 2), Dog(DogBreed.AKITA, 1), Dog(DogBreed.POMERANIAN, 6), Dog(DogBreed.SHIH_TZU, 5), Dog(DogBreed.DACHSHUND, 4) ) val cats = listOf(Cat(CatBreed.MAINE_COON), Cat(CatBreed.BALINESE), Cat(CatBreed.BENGAL)) val petsList = dogs.asSequence() .sortedBy { it.order } .map { DogItem(it) } .chunked(2) .flatMapIndexed { chunkIndex, dogGroup -> buildList { addAll(dogGroup) if (chunkIndex < cats.size) { add(CatItem(cats[chunkIndex])) } } } .toList() petsList.forEach { println(it) } }
优势
- 代码最简洁,利用Kotlin标准库函数简化逻辑
- 同样避免了低效的
removeAt(0)操作 - 流式处理,内存效率高
内容的提问来源于stack exchange,提问作者Anna Harrison
相关产品推荐
相关产品推荐

