我有一个Set<Point<double>>
,我想测试集合中是否包含特定的Point<double>
。
我的理解是,如果两个Point<double>
实例具有相同的hashCode
并根据==
相等,则默认的Set
实现会认为它们相同,并且会返回{ {1}},其中一个点位于集合中,我们使用true
测试其他点。
但是在以下示例中,情况似乎并非如此:
contains
import 'dart:math';
void main() {
final points = Set<Point<double>>.identity();
final a = Point<double>(5, 2);
final b = Point<double>(5, 2);
points.add(a);
print("a == b ? ${a == b}");
print("a.hashCode == b.hashCode ? ${a.hashCode == b.hashCode}");
print("points.contains(a) ? ${points.contains(a)}");
print("points.contains(b) ? ${points.contains(b)}");
}
我在哪里错了?
答案 0 :(得分:2)
Set<Point<double>>.identity()
使用身份哈希进行比较。但是Point
通过x和y相等(See source code)
因此,在这种情况下,a.idenityHash != a.hashcode
和a.idenityHash != b.idenityHash
即使a.hashCode == b.hashCode
也是如此。这一切都是因为==
和hashCode
被坐标进行对象比较而覆盖。
因此,如果创建正常集(使用hashCode方法进行比较),则会得到预期结果
final points = Set<Point<double>>();
points.add(a);
print("points.contains(b) ? ${points.contains(b)}"); // true
答案 1 :(得分:1)
之所以会发生这种情况,是因为不同的方式不同,但是您指定要通过身份而不是等效性来比较它们。
import 'dart:math';
void main() {
//final points = Set<Point<double>>.identity();
final points = Set<Point<double>>();
final a = Point<double>(5, 2);
final b = Point<double>(5, 2);
points.add(a);
print("a == b ? ${a == b}");
print("a.hashCode == b.hashCode ? ${a.hashCode == b.hashCode}");
print("points.contains(a) ? ${points.contains(a)}");
print("points.contains(b) ? ${points.contains(b)}");
}
您禁用了此运算符。
/**
* A `Point` is only equal to another `Point` with the same coordinates.
*
* This point is equal to `other` if, and only if,
* `other` is a `Point` with
* [x] equal to `other.x` and [y] equal to `other.y`.
*/
bool operator ==(dynamic other) =>
// Cannot change parameter type to `Object` in case some class
// inherits the type and uses their argument dynamically.
other is Point && x == other.x && y == other.y;
这是详细的解释(使用等于:相同)。
/**
* Creates an insertion-ordered identity-based set.
*
* Effectively a shorthand for:
*
* new LinkedHashSet<E>(equals: identical,
* hashCode: identityHashCode)
*/
external factory LinkedHashSet.identity();