Dart中Set<List>的元素检查与删除失效问题
Dart中Set<List>判断元素存在/删除失效的解决办法
问题根源
Dart里List是引用类型,Set判断元素是否相同,依赖对象的==运算符和hashCode方法。默认情况下,哪怕两个List内容完全一致,只要是不同的实例(内存引用不同),==就会返回false,hashCode也不相同。
你代码里add([1,1])添加的是一个List对象,后续调用contains([1,1])或remove([1,1])时,又新建了一个全新的List实例——这两个对象引用不同,所以Set不认它们是同一个元素,导致判断和删除操作失效。
解决办法
方法1:自定义类包装List,重写相等判断
自己写个类包裹List,手动实现基于内容的相等逻辑:
class DoubleList { final List<double> items; DoubleList(this.items); // 重写==,通过List内容判断相等性 @override bool operator ==(Object other) { if (identical(this, other)) return true; if (other is! DoubleList) return false; if (items.length != other.items.length) return false; for (int i = 0; i < items.length; i++) { if (items[i] != other.items[i]) return false; } return true; } // 基于List内容生成hashCode @override int get hashCode => Object.hashAll(items); // 方便打印查看结果 @override String toString() => items.toString(); } void main(List<String> args) { Set<DoubleList> level1barriers = {}; print(level1barriers); level1barriers.add(DoubleList([1, 1])); level1barriers.add(DoubleList([0.5, 0.3])); print(level1barriers); print(level1barriers.contains(DoubleList([1, 1]))); // 输出true level1barriers.remove(DoubleList([1, 1])); print(level1barriers); // 输出{[0.5, 0.3]} }
方法2:使用Tuple包(更简洁)
Dart的tuple包提供了不可变的Tuple类型,它的相等判断是基于内容实现的。先在pubspec.yaml中添加依赖:
dependencies: tuple: ^2.0.2
如果你的List固定是两个元素,就用Tuple2<double, double>:
import 'package:tuple/tuple.dart'; void main(List<String> args) { Set<Tuple2<double, double>> level1barriers = {}; print(level1barriers); level1barriers.add(const Tuple2(1, 1)); level1barriers.add(const Tuple2(0.5, 0.3)); print(level1barriers); print(level1barriers.contains(const Tuple2(1, 1))); // 输出true level1barriers.remove(const Tuple2(1, 1)); print(level1barriers); // 输出{(0.5, 0.3)} }
若List长度不固定,可使用tuple包中的ListTuple类型,同样支持按内容判断相等。
内容的提问来源于stack exchange,提问作者Sterlyn Agnar
相关产品推荐
相关产品推荐

