如何在SortedList中按指定条件查找并删除元素?——RecyclerView适配器场景下的实现疑问
我在OutlookItemsAdapter里写了这段代码:
class OutlookItemsAdapter : RecyclerView.Adapter<OutlookItemsViewHolder>() { companion object { lateinit var outlookItems: SortedList<OutlookItem> } init { outlookItems = SortedList(OutlookItem::class.java, object : SortedListAdapterCallback<OutlookItem>(this) { override fun areItemsTheSame(item1: OutlookItem, item2: OutlookItem): Boolean = item1 == item2 override fun compare(o1: OutlookItem, o2: OutlookItem): Int = o1.DateTime.compareTo(o2.DateTime) override fun areContentsTheSame(oldItem: OutlookItem, newItem: OutlookItem): Boolean = oldItem.EntryId.equals(newItem.EntryId) }) } }
OutlookItem的定义是:
class OutlookItem ( val Subject: String, val EntryId: String, val DateTime: LocalDateTime, val MeetingUrl: String? )
现在我需要写一个函数,接收EntryId参数,从outlookItems这个SortedList里删除对应的OutlookItem对象。但发现SortedList不支持用Lambda按条件查找删除,想问有没有简便的实现方法,还是必须自己写查找逻辑?
其实你不用太纠结,SortedList虽然没有直接的removeIf这类按条件删除的方法,但我们可以结合它提供的API来实现,不用从头写复杂的查找逻辑,给你两种简便的方式:
方式一:遍历查找后删除
因为SortedList实现了Iterable接口,所以可以直接用Kotlin的集合扩展方法快速找到匹配元素,然后删除:
fun deleteItemByEntryId(entryId: String) { // 找到第一个匹配EntryId的元素,找不到返回null val itemToRemove = outlookItems.firstOrNull { it.EntryId == entryId } itemToRemove?.let { outlookItems.remove(it) } }
这种方式代码简洁直观,适合大多数场景——只要你的列表元素数量不是特别大,完全够用,日常开发里这种写法最常见。
方式二:利用SortedList的有序特性优化查找效率
如果你的列表元素很多,遍历的O(n)效率不够看,可以借助SortedList的有序特性,用更高效的方式查找。不过这里需要先调整一下OutlookItem的相等判断逻辑:
首先重写OutlookItem的equals和hashCode方法,让它以EntryId作为相等判断的依据(毕竟EntryId是唯一标识):
class OutlookItem ( val Subject: String, val EntryId: String, val DateTime: LocalDateTime, val MeetingUrl: String? ) { override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false other as OutlookItem return EntryId == other.EntryId } override fun hashCode(): Int { return EntryId.hashCode() } }
然后就可以用SortedList的indexOf方法快速定位元素位置,再删除:
fun deleteItemByEntryId(entryId: String) { // 创建一个仅EntryId匹配的占位对象,用于查找 val placeholderItem = OutlookItem("", entryId, LocalDateTime.MIN, null) val index = outlookItems.indexOf(placeholderItem) if (index != -1) { outlookItems.removeItemAt(index) } }
这种方式的查找时间复杂度是O(log n),比遍历的O(n)高效很多,适合数据量较大的场景。
另外提个小建议:把outlookItems放在companion object里会变成全局共享状态,如果同时存在多个OutlookItemsAdapter实例,很容易出问题,建议改成类的成员变量哦。
内容的提问来源于stack exchange,提问作者Tar

