Document isValidKey for {Linked,}Hash{Map,Set}.

Closes #26498, #26499

Bug: https://dartbug.com/26498
Change-Id: I9041d4f511d0a4dc8d1315d5c434c2975a43e619
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/219780
Auto-Submit: Lasse R.H. Nielsen <lrn@google.com>
Commit-Queue: Lasse R.H. Nielsen <lrn@google.com>
Reviewed-by: Nate Bosch <nbosch@google.com>
This commit is contained in:
Lasse R.H. Nielsen 2021-11-10 18:39:27 +00:00 committed by commit-bot@chromium.org
parent 7fabfa7efd
commit cb4c4f9ea9
4 changed files with 78 additions and 82 deletions

View file

@ -37,40 +37,13 @@ abstract class HashMap<K, V> implements Map<K, V> {
/// values, the iteration order is unspecified except that it will stay the
/// same as long as the map isn't changed.
///
/// If [equals] is provided, it is used to compare the keys in the table with
/// If [equals] is provided, it is used to compare the keys in the map with
/// new keys. If [equals] is omitted, the key's own [Object.==] is used
/// instead.
///
/// Similar, if [hashCode] is provided, it is used to produce a hash value
/// for keys in order to place them in the hash table. If it is omitted, the
/// key's own [Object.hashCode] is used.
///
/// If using methods like [operator []], [remove] and [containsKey] together
/// with a custom equality and hashcode, an extra `isValidKey` function
/// can be supplied. This function is called before calling [equals] or
/// [hashCode] with an argument that may not be a [K] instance, and if the
/// call returns false, the key is assumed to not be in the set.
/// The [isValidKey] function defaults to just testing if the object is a
/// [K] instance.
///
/// Example:
/// ```dart template:expression
/// HashMap<int,int>(equals: (int a, int b) => (b - a) % 5 == 0,
/// hashCode: (int e) => e % 5)
/// ```
/// This example map does not need an `isValidKey` function to be passed.
/// The default function accepts only `int` values, which can safely be
/// passed to both the `equals` and `hashCode` functions.
///
/// If neither `equals`, `hashCode`, nor `isValidKey` is provided,
/// the default `isValidKey` instead accepts all keys.
/// The default equality and hashcode operations are assumed to work on all
/// objects.
///
/// Likewise, if `equals` is [identical], `hashCode` is [identityHashCode]
/// and `isValidKey` is omitted, the resulting map is identity based,
/// and the `isValidKey` defaults to accepting all keys.
/// Such a map can be created directly using [HashMap.identity].
/// for keys in order to place them in the map. If [hashCode] is omitted,
/// the key's own [Object.hashCode] is used.
///
/// The used `equals` and `hashCode` method should always be consistent,
/// so that if `equals(a, b)` then `hashCode(a) == hashCode(b)`. The hash
@ -79,7 +52,36 @@ abstract class HashMap<K, V> implements Map<K, V> {
/// unpredictable.
///
/// If you supply one of [equals] and [hashCode],
/// you should generally also to supply the other.
/// you should generally also supply the other.
///
/// Some [equals] or [hashCode] functions might not work for all objects.
/// If [isValidKey] is supplied, it's used to check a potential key
/// which is not necessarily an instance of [K], like the arguments to
/// [operator []], [remove] and [containsKey], which are typed as `Object?`.
/// If [isValidKey] returns `false`, for an object, the [equals] and
/// [hashCode] functions are not called, and no key equal to that object
/// is assumed to be in the map.
/// The [isValidKey] function defaults to just testing if the object is an
/// instance of [K].
///
/// Example:
/// ```dart template:expression
/// HashMap<int,int>(equals: (int a, int b) => (b - a) % 5 == 0,
/// hashCode: (int e) => e % 5)
/// ```
/// This example map does not need an `isValidKey` function to be passed.
/// The default function accepts precisely `int` values, which can safely be
/// passed to both the `equals` and `hashCode` functions.
///
/// If neither `equals`, `hashCode`, nor `isValidKey` is provided,
/// the default `isValidKey` instead accepts all keys.
/// The default equality and hashcode operations are known to work on all
/// objects.
///
/// Likewise, if `equals` is [identical], `hashCode` is [identityHashCode]
/// and `isValidKey` is omitted, the resulting map is identity based,
/// and the `isValidKey` defaults to accepting all keys.
/// Such a map can be created directly using [HashMap.identity].
external factory HashMap(
{bool Function(K, K)? equals,
int Function(K)? hashCode,
@ -87,6 +89,9 @@ abstract class HashMap<K, V> implements Map<K, V> {
/// Creates an unordered identity-based map.
///
/// Keys of this map are considered equal only to the same object,
/// and does not use [Object.==] at all.
///
/// Effectively a shorthand for:
/// ```dart
/// HashMap<K, V>(equals: identical, hashCode: identityHashCode)

View file

@ -25,12 +25,7 @@ abstract class HashSet<E> implements Set<E> {
/// Create a hash set using the provided [equals] as equality.
///
/// The provided [equals] must define a stable equivalence relation, and
/// [hashCode] must be consistent with [equals]. If the [equals] or [hashCode]
/// methods won't work on all objects, but only on some instances of E, the
/// [isValidKey] predicate can be used to restrict the keys that the functions
/// are applied to.
/// Any key for which [isValidKey] returns false is automatically assumed
/// to not be in the set when asking `contains`.
/// [hashCode] must be consistent with [equals].
///
/// If [equals] or [hashCode] are omitted, the set uses
/// the elements' intrinsic [Object.==] and [Object.hashCode].
@ -38,18 +33,20 @@ abstract class HashSet<E> implements Set<E> {
/// If you supply one of [equals] and [hashCode],
/// you should generally also to supply the other.
///
/// If the supplied `equals` or `hashCode` functions won't work on all [E]
/// objects, and the map will be used in a setting where a non-`E` object
/// is passed to, e.g., `contains`, then the [isValidKey] function should
/// also be supplied.
///
/// If [isValidKey] is omitted, it defaults to testing if the object is an
/// [E] instance. That means that:
/// Some [equals] or [hashCode] functions might not work for all objects.
/// If [isValidKey] is supplied, it's used to check a potential element
/// which is not necessarily an instance of [E], like the argument to
/// [contains] which is typed as `Object?`.
/// If [isValidKey] returns `false`, for an object, the [equals] and
/// [hashCode] functions are not called, and no key equal to that object
/// is assumed to be in the map.
/// The [isValidKey] function defaults to just testing if the object is an
/// instance of [E], which means that:
/// ```dart template:expression
/// HashSet<int>(equals: (int e1, int e2) => (e1 - e2) % 5 == 0,
/// hashCode: (int e) => e % 5)
/// ```
/// does not need an `isValidKey` argument, because it defaults to only
/// does not need an `isValidKey` argument because it defaults to only
/// accepting `int` values which are accepted by both `equals` and `hashCode`.
///
/// If neither `equals`, `hashCode`, nor `isValidKey` is provided,

View file

@ -8,7 +8,7 @@ part of dart.collection;
///
/// The insertion order of keys is remembered,
/// and keys are iterated in the order they were inserted into the map.
/// Values are iterated in their corresponding key's order.
/// Values and entries are iterated in their corresponding key's order.
/// Changing a key's value, when the key is already in the map,
/// does not change the iteration order,
/// but removing the key and adding it again
@ -30,21 +30,31 @@ abstract class LinkedHashMap<K, V> implements Map<K, V> {
/// for keys in order to place them in the hash table. If it is omitted, the
/// key's own [Object.hashCode] is used.
///
/// If using methods like [operator []], [remove] and [containsKey] together
/// with a custom equality and hashcode, an extra `isValidKey` function
/// can be supplied. This function is called before calling [equals] or
/// [hashCode] with an argument that may not be a [K] instance, and if the
/// call returns false, the key is assumed to not be in the set.
/// The [isValidKey] function defaults to just testing if the object is a
/// [K] instance.
/// The used `equals` and `hashCode` method should always be consistent,
/// so that if `equals(a, b)` then `hashCode(a) == hashCode(b)`. The hash
/// of an object, or what it compares equal to, should not change while the
/// object is in the table. If it does change, the result is unpredictable.
///
/// If you supply one of [equals] and [hashCode],
/// you should generally also supply the other.
///
/// Some [equals] or [hashCode] functions might not work for all objects.
/// If [isValidKey] is supplied, it's used to check a potential key
/// which is not necessarily an instance of [K], like the arguments to
/// [operator []], [remove] and [containsKey], which are typed as `Object?`.
/// If [isValidKey] returns `false`, for an object, the [equals] and
/// [hashCode] functions are not called, and no key equal to that object
/// is assumed to be in the map.
/// The [isValidKey] function defaults to just testing if the object is an
/// instance of [K].
///
/// Example:
/// ```dart template:expression
/// LinkedHashMap<int,int>(equals: (int a, int b) => (b - a) % 5 == 0,
/// hashCode: (int e) => e % 5)
/// LikedHashMap<int,int>(equals: (int a, int b) => (b - a) % 5 == 0,
/// hashCode: (int e) => e % 5)
/// ```
/// This example map does not need an `isValidKey` function to be passed.
/// The default function accepts only `int` values, which can safely be
/// The default function accepts precisely `int` values, which can safely be
/// passed to both the `equals` and `hashCode` functions.
///
/// If neither `equals`, `hashCode`, nor `isValidKey` is provided,
@ -56,14 +66,6 @@ abstract class LinkedHashMap<K, V> implements Map<K, V> {
/// and `isValidKey` is omitted, the resulting map is identity based,
/// and the `isValidKey` defaults to accepting all keys.
/// Such a map can be created directly using [LinkedHashMap.identity].
///
/// The used `equals` and `hashCode` method should always be consistent,
/// so that if `equals(a, b)` then `hashCode(a) == hashCode(b)`. The hash
/// of an object, or what it compares equal to, should not change while the
/// object is in the table. If it does change, the result is unpredictable.
///
/// If you supply one of [equals] and [hashCode],
/// you should generally also to supply the other.
external factory LinkedHashMap(
{bool Function(K, K)? equals,
int Function(K)? hashCode,

View file

@ -30,28 +30,20 @@ abstract class LinkedHashSet<E> implements Set<E> {
/// [equals] and [hashCode].
///
/// The provided [equals] must define a stable equivalence relation, and
/// [hashCode] must be consistent with [equals]. If the [equals] or [hashCode]
/// methods won't work on all objects, but only on some instances of E, the
/// [isValidKey] predicate can be used to restrict the keys that the functions
/// are applied to.
/// Any key for which [isValidKey] returns false is automatically assumed
/// to not be in the set when asking `contains`.
///
/// If [equals] or [hashCode] are omitted, the set uses
/// the elements' intrinsic [Object.==] and [Object.hashCode],
/// and [isValidKey] is ignored since these operations are assumed
/// to work on all objects.
/// [hashCode] must be consistent with [equals].
///
/// If you supply one of [equals] and [hashCode],
/// you should generally also to supply the other.
///
/// If the supplied `equals` or `hashCode` functions won't work on all [E]
/// objects, and the map will be used in a setting where a non-`E` object
/// is passed to, e.g., `contains`, then the [isValidKey] function should
/// also be supplied.
///
/// If [isValidKey] is omitted, it defaults to testing if the object is an
/// [E] instance. That means that:
/// Some [equals] or [hashCode] functions might not work for all objects.
/// If [isValidKey] is supplied, it's used to check a potential element
/// which is not necessarily an instance of [E], like the argument to
/// [contains] which is typed as `Object?`.
/// If [isValidKey] returns `false`, for an object, the [equals] and
/// [hashCode] functions are not called, and no key equal to that object
/// is assumed to be in the map.
/// The [isValidKey] function defaults to just testing if the object is an
/// instance of [E], which means that:
/// ```dart template:expression
/// LinkedHashSet<int>(equals: (int e1, int e2) => (e1 - e2) % 5 == 0,
/// hashCode: (int e) => e % 5)