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

SplayTreeSet重复元素问题:如何使其使用重载的equals方法?

解决SplayTreeSet重复元素问题:让集合使用自定义相等判断

问题根源

Dart的SplayTreeSet(包括通过ObservableSet.splayTreeSetFrom创建的实例)不依赖你重载的operator==和hashCode判断元素是否相等,它完全基于传入的compare比较器:当compare(a, b)返回0时,就认为a和b是同一个元素,不会重复添加;反之,哪怕两个元素的==返回true,只要compare结果不为0,就会被当成不同元素存入集合。

你的当前compare逻辑是按createTime排序,所以即使两个元素的chatRoomId相同(你的相等判断规则),只要createTime不同,compare就不会返回0,集合就会判定为不同元素,导致重复添加。而调用toSet()后重复消失,是因为普通Set(如HashSet)是用operator==和hashCode去重的,刚好符合你的判断规则。

解决方案

修改compare比较器,先按chatRoomId判断元素是否相等(返回0),再按createTime排序。有两种实现方式:

方式一:修改模型的compareTo方法

调整ChatRoomListModel的compareTo逻辑,优先比较chatRoomId:

int compareTo(ChatRoomListModel other) {
  // 先比较chatRoomId,相同则视为同一元素
  final idComparison = messagesModel.chatRoomId.compareTo(other.messagesModel.chatRoomId);
  if (idComparison != 0) {
    // id不同时,按createTime正序排序(配合集合的倒序参数实现最终倒序)
    return messagesModel.createTime.compareTo(other.messagesModel.createTime);
  }
  return 0;
}

集合的初始化代码保持不变:

ObservableSet<ChatRoomListModel> _latestMessages = ObservableSet.splayTreeSetFrom(
  ObservableSet(),
  compare: (a, b) => b.compareTo(a), // 保持按createTime倒序排列
);

方式二:直接在集合的compare参数中处理

无需修改模型,直接在创建集合时定义比较逻辑:

ObservableSet<ChatRoomListModel> _latestMessages = ObservableSet.splayTreeSetFrom(
  ObservableSet(),
  compare: (a, b) {
    // 优先判断chatRoomId是否相同,相同则返回0(视为同一元素)
    final idCompare = a.messagesModel.chatRoomId.compareTo(b.messagesModel.chatRoomId);
    if (idCompare != 0) {
      // id不同时,按createTime倒序排序
      return b.messagesModel.createTime.compareTo(a.messagesModel.createTime);
    }
    return 0;
  },
);

验证

修改后,添加chatRoomId相同的元素时,compare会返回0,集合会判定为重复元素而拒绝添加;不同chatRoomId的元素则按createTime排序存入,同时contains方法也会基于compare逻辑正确返回结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 09:31:05