Different ways to create a HashSet in Dart

Different ways to create a HashSet in Dart:

There are four different ways to create the constructor of a HashSet in Dart. In this post, we will learn how these constructors work with examples.

Method 1: By using the default HashSet constructor:

The default constructor of HashSet is:

HashSet({bool equals(E, E)?, int hashCode(E)?, bool isValidKey(dynamic)?})

This method creates one HashSet. Optionally, it takes three parameters:

  • The equals method is used to provide an equivalence relation. By default, it uses Object.==.
  • The hashCode method is used to find the hash value for an object. It uses Object.hashCode by default.
  • The isValidKey method is used to check if the object is an instance of E or not. By default, isValidKey accepts all keys.

Example:

import 'dart:collection';

void main() {
  final hashSet = HashSet();
  hashSet.add(1);
  hashSet.add(2);
  hashSet.add(3);

  print("HashSet: ${hashSet}");
}

It will print:

HashSet: {1, 2, 3}

Let’s take another example with equals and hashCode:

import 'dart:collection';

void main() {
  final hashSet = HashSet(
      equals: (int e1, int e2) => e1 % 3 == e2 % 3, hashCode: (int e) => e % 3);

  hashSet.add(1);
  hashSet.add(2);
  hashSet.add(3);
  hashSet.add(4);
  hashSet.add(5);
  hashSet.add(6);

  print("HashSet: ${hashSet}");
}

Here, the equals method will consider two numbers equal if the value of modulo 3 is equal for both. The hashCode method returns the value of modulo 3 of the number.

If you run this program, it will print:

HashSet: {3, 1, 2}

As you can see here, 4, 5 and 6 are not added to the hashSet since the value of modulo 3 of these numbers is equal to 1, 2 and 3.

Method 2: Create one identity-based HashSet:

The method HashSet.identity() creates one identity-based HashSet. This is defined as:

HashSet.identity()

Example:

import 'dart:collection';

void main() {
  final hashSet = HashSet.identity();

  hashSet.add(1);
  hashSet.add(2);
  hashSet.add(3);
  hashSet.add(4);
  hashSet.add(5);
  hashSet.add(6);

  print("HashSet: ${hashSet}");
}

It will print:

HashSet: {1, 2, 3, 4, 5, 6}

Create a HashSet from an iterable:

The HashSet.from method creates one HashSet from the content of an iterable.

HashSet.from(Iterable it)

This method creates one HashSet by HashSet() and adds all the elements of the iterable in order. If two equal elements are found, the first one is added.

import 'dart:collection';

void main() {
  final nos = [1, 2, 3, 4];
  final hashSet = HashSet<int>.from(nos);

  print("HashSet: ${hashSet}");
}

It will print:

HashSet: {1, 2, 3}

There is another method, HashSet.of to create a HashSet from an iterable. This method is defined as:

HashSet.of(Iterable<E> it)

It uses the HashSet() constructor to create one HashSet and adds all the elements of the iterable by using the addAll method.

import 'dart:collection';

void main() {
  final nos = [1, 2, 3, 4];
  final hashSet = HashSet<int>.of(nos);

  print("HashSet: ${hashSet}");
}

It will give the same result.

Difference between HashSet.of and HashSet.from:

Both of these methods look similar, but there are differences between them.

  • The main difference is that HashSet.of(Iterable<E> it) takes an iterable with an explicit type. But HashSet.from(Iterable it) can take an iterable of any type.

The HashSet.from is used for downcasting. For example,

import 'dart:collection';

void main() {
  final nos = <Object>{'A', 'B', 'C', 'D'};
  final hashSet = HashSet<String>.from(nos);

  print("HashSet: ${hashSet}");
}

It will down-cast the elements from Object to String.

HashSet: {A, D, C, B}

But, if we try to use HashSet.of, it will throw one error. Because we need to provide the iterable of the same type as the final HashSet.

You might also like: