Add EqualityMap and EqualitySet. (#35)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 74710a3..fa10220 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 1.11.0
+
+* Add `EqualityMap` and `EqualitySet` classes which use `Equality` objects for
+  key and element equality, respectively.
+
 ## 1.10.1
 
 * `Set.difference` now takes a `Set<Object>` as argument.
diff --git a/lib/collection.dart b/lib/collection.dart
index 58d98f7..612508b 100644
--- a/lib/collection.dart
+++ b/lib/collection.dart
@@ -6,6 +6,8 @@
 export "src/canonicalized_map.dart";
 export "src/comparators.dart";
 export "src/equality.dart";
+export "src/equality_map.dart";
+export "src/equality_set.dart";
 export "src/functions.dart";
 export "src/iterable_zip.dart";
 export "src/priority_queue.dart";
diff --git a/lib/src/equality_map.dart b/lib/src/equality_map.dart
new file mode 100644
index 0000000..686e5bd
--- /dev/null
+++ b/lib/src/equality_map.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:collection';
+
+import 'equality.dart';
+import 'wrappers.dart';
+
+/// A [Map] whose key equality is determined by an [Equality] object.
+class EqualityMap<K, V> extends DelegatingMap<K, V> {
+  /// Creates a map with equality based on [equality].
+  EqualityMap(Equality<K> equality)
+      : super(new LinkedHashMap(
+            equals: equality.equals,
+            hashCode: equality.hash,
+            isValidKey: equality.isValidKey));
+
+  /// Creates a map with equality based on [equality] that contains all
+  /// key-value pairs of [other].
+  ///
+  /// If [other] has multiple keys that are equivalent according to [equality],
+  /// the last one reached during iteration takes precedence.
+  EqualityMap.from(Equality<K> equality, Map<K, V> other)
+      : super(new LinkedHashMap(
+            equals: equality.equals,
+            hashCode: equality.hash,
+            isValidKey: equality.isValidKey)) {
+    addAll(other);
+  }
+}
+
diff --git a/lib/src/equality_set.dart b/lib/src/equality_set.dart
new file mode 100644
index 0000000..b0582ce
--- /dev/null
+++ b/lib/src/equality_set.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:collection';
+
+import 'equality.dart';
+import 'wrappers.dart';
+
+/// A [Map] whose key equality is determined by an [Equality] object.
+class EqualitySet<E> extends DelegatingSet<E> {
+  /// Creates a set with equality based on [equality].
+  EqualitySet(Equality<E> equality)
+      : super(new LinkedHashSet(
+            equals: equality.equals,
+            hashCode: equality.hash,
+            isValidKey: equality.isValidKey));
+
+  /// Creates a set with equality based on [equality] that contains all
+  /// elements in [other].
+  ///
+  /// If [other] has multiple values that are equivalent according to
+  /// [equality], the first one reached during iteration takes precedence.
+  EqualitySet.from(Equality<E> equality, Iterable<E> other)
+      : super(new LinkedHashSet(
+            equals: equality.equals,
+            hashCode: equality.hash,
+            isValidKey: equality.isValidKey)) {
+    addAll(other);
+  }
+}
+
diff --git a/pubspec.yaml b/pubspec.yaml
index f92b73d..13b81f2 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: collection
-version: 1.10.1
+version: 1.11.0
 author: Dart Team <misc@dartlang.org>
 description: Collections and utilities functions and classes related to collections.
 homepage: https://www.github.com/dart-lang/collection
diff --git a/test/equality_map_test.dart b/test/equality_map_test.dart
new file mode 100644
index 0000000..8225efd
--- /dev/null
+++ b/test/equality_map_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:collection/collection.dart';
+import 'package:test/test.dart';
+
+void main() {
+  test("uses the given equality", () {
+    var map = new EqualityMap(const IterableEquality());
+    expect(map, isEmpty);
+
+    map[[1, 2, 3]] = 1;
+    expect(map, containsPair([1, 2, 3], 1));
+
+    map[[1, 2, 3]] = 2;
+    expect(map, containsPair([1, 2, 3], 2));
+
+    map[[2, 3, 4]] = 3;
+    expect(map, containsPair([1, 2, 3], 2));
+    expect(map, containsPair([2, 3, 4], 3));
+  });
+
+  test("EqualityMap.from() prefers the lattermost equivalent key", () {
+    var map = new EqualityMap.from(const IterableEquality(), {
+      [1, 2, 3]: 1,
+      [2, 3, 4]: 2,
+      [1, 2, 3]: 3,
+      [2, 3, 4]: 4,
+      [1, 2, 3]: 5,
+      [1, 2, 3]: 6,
+    });
+
+    expect(map, containsPair([1, 2, 3], 6));
+    expect(map, containsPair([2, 3, 4], 4));
+  });
+}
diff --git a/test/equality_set_test.dart b/test/equality_set_test.dart
new file mode 100644
index 0000000..1b20684
--- /dev/null
+++ b/test/equality_set_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:collection/collection.dart';
+import 'package:test/test.dart';
+
+void main() {
+  test("uses the given equality", () {
+    var set = new EqualitySet(const IterableEquality());
+    expect(set, isEmpty);
+
+    var list1 = [1, 2, 3];
+    expect(set.add(list1), isTrue);
+    expect(set, contains([1, 2, 3]));
+    expect(set, contains(same(list1)));
+
+    var list2 = [1, 2, 3];
+    expect(set.add(list2), isFalse);
+    expect(set, contains([1, 2, 3]));
+    expect(set, contains(same(list1)));
+    expect(set, isNot(contains(same(list2))));
+
+    var list3 = [2, 3, 4];
+    expect(set.add(list3), isTrue);
+    expect(set, contains(same(list1)));
+    expect(set, contains(same(list3)));
+  });
+
+  test("EqualitySet.from() prefers the lattermost equivalent value", () {
+    var list1 = [1, 2, 3];
+    var list2 = [2, 3, 4];
+    var list3 = [1, 2, 3];
+    var list4 = [2, 3, 4];
+    var list5 = [1, 2, 3];
+    var list6 = [1, 2, 3];
+
+    var set = new EqualitySet.from(const IterableEquality(),
+        [list1, list2, list3, list4, list5, list6]);
+
+    expect(set, contains(same(list1)));
+    expect(set, contains(same(list2)));
+    expect(set, isNot(contains(same(list3))));
+    expect(set, isNot(contains(same(list4))));
+    expect(set, isNot(contains(same(list5))));
+    expect(set, isNot(contains(same(list6))));
+  });
+}