// Copyright (c) 2013, 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.

part of dart.collection;

/// An unordered hash-table based [Set] implementation.
///
/// The elements of a `HashSet` must have consistent equality
/// and hashCode implementations. This means that the equals operation
/// must define a stable equivalence relation on the elements (reflexive,
/// symmetric, transitive, and consistent over time), and that the hashCode
/// must be consistent with equality, so that it's the same for objects that are
/// considered equal.
///
/// Most simple operations on `HashSet` are done in (potentially amortized)
/// constant time: [add], [contains], [remove], and [length], provided the hash
/// codes of objects are well distributed.
///
/// **The iteration order of the set is not specified and depends on
/// the hashcodes of the provided elements.** However, the order is stable:
/// multiple iterations over the same set produce the same order, as long as
/// the set is not modified.
///
/// **Note:**
/// Do not modify a set (add or remove elements) while an operation
/// is being performed on that set, for example in functions
/// called during a [forEach] or [containsAll] call,
/// or while iterating the set.
///
/// Do not modify elements in a way which changes their equality (and thus their
/// hash code) while they are in the set. Some specialized kinds of sets may be
/// more permissive with regards to equality, in which case they should document
/// their different behavior and restrictions.
///
/// Example:
/// ```dart
/// final letters = HashSet<String>();
/// ```
/// To add data to a set, use  [add] or [addAll].
/// ```
/// letters.add('A');
/// letters.addAll({'B', 'C', 'D'});
/// ```
/// To check if the set is empty, use [isEmpty] or [isNotEmpty].
/// To find the number of elements in the set, use [length].
/// ```
/// print(letters.isEmpty); // false
/// print(letters.length); // 4
/// print(letters); // fx {A, D, C, B}
/// ```
/// To check whether the set has an element with a specific value,
/// use [contains].
/// ```
/// final bExists = letters.contains('B'); // true
/// ```
/// The [forEach] method calls a function with each element of the set.
/// ```
/// letters.forEach(print);
/// // A
/// // D
/// // C
/// // B
/// ```
/// To make a copy of the set, use [toSet].
/// ```
/// final anotherSet = letters.toSet();
/// print(anotherSet); // fx {A, C, D, B}
/// ```
/// To remove an element, use [remove].
/// ```
/// final removedValue = letters.remove('A'); // true
/// print(letters); // fx {B, C, D}
/// ```
/// To remove multiple elements at the same time, use [removeWhere] or
/// [removeAll].
/// ```
/// letters.removeWhere((element) => element.startsWith('B'));
/// print(letters); // fx {D, C}
/// ```
/// To removes all elements in this set that do not meet a condition,
/// use [retainWhere].
/// ```
/// letters.retainWhere((element) => element.contains('C'));
/// print(letters); // {C}
/// ```
/// To remove all elements and empty the set, use [clear].
/// ```
/// letters.clear();
/// print(letters.isEmpty); // true
/// print(letters); // {}
/// ```
/// **See also:**
/// * [Set] is the general interface of collection where each object can
/// occur only once.
/// * [LinkedHashSet] objects stored based on insertion order.
/// * [SplayTreeSet] iterates the objects in sorted order.
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 [equals] or [hashCode] are omitted, the set uses
  /// the elements' intrinsic [Object.==] and [Object.hashCode].
  ///
  /// 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 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
  /// accepting `int` values which are accepted by both `equals` and `hashCode`.
  ///
  /// If neither `equals`, `hashCode`, nor `isValidKey` is provided,
  /// the default `isValidKey` instead accepts all values.
  /// 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 set is identity based,
  /// and the `isValidKey` defaults to accepting all keys.
  /// Such a map can be created directly using [HashSet.identity].
  external factory HashSet(
      {bool Function(E, E)? equals,
      int Function(E)? hashCode,
      bool Function(dynamic)? isValidKey});

  /// Creates an unordered identity-based set.
  ///
  /// Effectively shorthand for:
  /// ```dart
  /// HashSet<E>(equals: identical, hashCode: identityHashCode)
  /// ```
  external factory HashSet.identity();

  /// Create a hash set containing all [elements].
  ///
  /// Creates a hash set as by `HashSet<E>()` and adds all given [elements]
  /// to the set. The elements are added in order. If [elements] contains
  /// two entries that are equal, but not identical, then the first one is
  /// the one in the resulting set.
  ///
  /// All the [elements] should be instances of [E].
  /// The `elements` iterable itself may have any element type, so this
  /// constructor can be used to down-cast a `Set`, for example as:
  /// ```dart
  /// Set<SuperType> superSet = ...;
  /// Set<SubType> subSet =
  ///     HashSet<SubType>.from(superSet.whereType<SubType>());
  /// ```
  /// Example:
  /// ```dart
  /// final numbers = <num>[10, 20, 30];
  /// final hashSetFrom = HashSet<int>.from(numbers);
  /// print(hashSetFrom); // fx {20, 10, 30}
  /// ```
  factory HashSet.from(Iterable<dynamic> elements) {
    HashSet<E> result = HashSet<E>();
    for (final e in elements) {
      result.add(e as E);
    }
    return result;
  }

  /// Create a hash set containing all [elements].
  ///
  /// Creates a hash set as by `HashSet<E>()` and adds all given [elements]
  /// to the set. The elements are added in order. If [elements] contains
  /// two entries that are equal, but not identical, then the first one is
  /// the one in the resulting set.
  /// Example:
  /// ```dart
  /// final baseSet = <int>{1, 2, 3};
  /// final hashSetOf = HashSet<num>.of(baseSet);
  /// print(hashSetOf); // fx {3, 1, 2}
  /// ```
  factory HashSet.of(Iterable<E> elements) => HashSet<E>()..addAll(elements);

  /// Provides an iterator that iterates over the elements of this set.
  ///
  /// The order of iteration is unspecified,
  /// but is consistent between changes to the set.
  Iterator<E> get iterator;
}
