为什么Set不包含Point

时间:2019-03-04 11:40:55

标签: dart

我有一个Set<Point<double>>,我想测试集合中是否包含特定的Point<double>

我的理解是,如果两个Point<double>实例具有相同的hashCode并根据==相等,则默认的Set实现会认为它们相同,并且会返回{ {1}},其中一个点位于集合中,我们使用true测试其他点。

但是在以下示例中,情况似乎并非如此:

contains

According to DartPad输出为:

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)}");  
}

我在哪里错了?

2 个答案:

答案 0 :(得分:2)

Set<Point<double>>.identity()使用身份哈希进行比较。但是Point通过x和y相等(See source code)

覆盖了比较。

因此,在这种情况下,a.idenityHash != a.hashcodea.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();