Kotlin中如何根据特定条件从MutableList移除元素
基于Kotlin Flow实现带超时自动移除的扫描列表管理
核心需求梳理
- 向MutableList中添加唯一的扫描结果元素(避免重复)
- 实现两种元素移除逻辑:
- 当扫描Flow停止发射数据时,处理列表清理
- 某个元素最后一次被扫描到后,超过30秒未再次出现则自动移除
优化后的完整实现代码
import kotlinx.coroutines.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.onCompletion import java.util.concurrent.ConcurrentHashMap class ItemList { // 适配Compose:如果需要自动触发重组,替换为mutableStateListOf<ScanResults>() val scanResultList = mutableListOf<ScanResults>() // 记录每个设备最后一次被扫描到的时间戳,线程安全的Map private val lastSeenTimestamps = ConcurrentHashMap<Device, Long>() // 定期清理超时元素的后台协程任务 private var cleanupJob: Job? = null fun simulateScanFlow(): Flow<ScanResults> = flow { (0..20).forEach { delay(200L) val result = when (it) { in 10..12 -> ScanResults(Device("item in 10-12 range")) in 15..18 -> ScanResults(Device("item in 15-18 range")) else -> ScanResults(Device("item out of range")) } emit(result) } } fun startScanning() = runBlocking { // 启动每秒一次的超时检查任务 cleanupJob = launch { while (isActive) { delay(1000L) removeTimeoutItems() } } simulateScanFlow() .catch { e -> println("扫描异常: ${e.message}") } .onCompletion { // Flow停止发射时,停止清理任务并清空列表 cleanupJob?.cancel() scanResultList.clear() lastSeenTimestamps.clear() println("扫描已停止,列表已清空") } .collect { result -> processScanResult(result) } } private fun processScanResult(result: ScanResults) { result.device?.let { device -> // 更新当前设备的最后活跃时间 lastSeenTimestamps[device] = System.currentTimeMillis() // 仅当列表中无重复元素时添加 if (!scanResultList.contains(result)) { scanResultList.add(result) println("已添加元素: ${device.name}") } } } private fun removeTimeoutItems() { val currentTime = System.currentTimeMillis() // 筛选出超过30秒未出现的设备 val timeoutDevices = lastSeenTimestamps.filter { (_, timestamp) -> currentTime - timestamp > 30000L }.keys timeoutDevices.forEach { device -> scanResultList.removeIf { it.device == device } lastSeenTimestamps.remove(device) println("已移除超时元素: ${device.name}") } } data class ScanResults(val device: Device? = null) data class Device(val name: String? = null) } fun main() { ItemList().startScanning() }
关键实现说明
超时元素自动移除
- 用
lastSeenTimestamps记录每个设备的最后扫描时间,通过后台协程每秒检查一次 - 一旦设备超过30秒未被扫描到,就从列表和时间戳映射中移除,确保列表只保留活跃的扫描结果
- 用
Flow停止时的清理逻辑
- 通过
onCompletion操作符监听Flow的结束事件(包括正常完成、异常终止) - 此时取消后台清理任务,清空扫描列表和时间戳映射,完成收尾工作
- 通过
重复元素判断优化
- 由于
ScanResults和Device都是data class,默认实现了equals和hashCode,直接用contains就能判断元素是否重复,省去了额外的重复检查方法
- 由于
Compose适配注意
- 如果需要在Compose中使用,将
mutableListOf替换为mutableStateListOf,这样列表的变化会自动触发Compose重组,完全满足你无法使用Set的场景需求
- 如果需要在Compose中使用,将
内容的提问来源于stack exchange,提问作者Compose Learner
相关产品推荐
相关产品推荐

