Maps & Sets in JavaScript
Tags: javascript, webdev, programming
Published: 2022-03-09 13:00:34

In JavaScript, objects are wonderfully versatile, and arrays are wonderfully fast. But a couple more items sit in the middle of these two; the lesser know `Map` and `Set`.

Designed to make data access faster and simpler, you’ll be hard-pressed to find a coding challenge site that doesn’t involve at least one of these (typically `Map`) on more than a few of their challenges.

`Map` and `Set` share some things, so let’s kick things off with `Map`.

## Map

A `Map` is a key-value store (much like an object), that will allow you you to use just about anything you want as a key, maintains insertion order, has a size property, and rejects duplicate keys. Now that’s a lot of features right there, so let’s look at a basic example first:

{% embed https://gist.github.com/DuncanMcArdle/6636a07a639e6cdd1b6ecb1e8668c2b3 %}

Straight away you can begin to see the performance advantages of a `Map`. No more looping through massive data-sets to find what you need, just call `Map.get()` and you’re done! The classic example for a good `Map` is often a phone-book, and that makes sense, because you can imagine how efficient it is to call upon any random contact from a phone-book using a `Map`, which knows each and every entry in there by heart.

### Keys in a Map

But `Map` is also incredibly versatile. Unlike arrays, it’ll let you use just about whatever you want as a key, whether it be strings, integers, objects, or even functions!

{% embed https://gist.github.com/DuncanMcArdle/0da1d0c056b0b140dd8e989901bfd110 %}

### Looping through a Map

A `Map` will also retain its insertion order, which is incredibly important when you want to know what came first. Now of course, `Map` isn’t an array, so you can’t call `mapName[0]` to get the first entry (as `0` is a valid key for a `Map`!), so you might be wondering why insertion order matters?

Well, `Map` also come with a variety of methods you’ll find familiar from [my post on for loops](https://dev.to/duncanmcardle/battle-of-the-javascript-for-loops-for-forin-forof-foreach-etc-4lae), such as `Map.values()` , `Map.keys()` , `Map.entries()` and the infamous `forEach()` , all of which benefit from the original data being in the order it was inserted.

{% embed https://gist.github.com/DuncanMcArdle/79c30d74b0fe7975a3040164f09b7864 %}

### Duplication in a Map

Finally it’s worth pointing out another helpful `Map` function: `Map.has()` . This is a simple utility for checking whether a given key already exists in a `Map`, and can therefore be used to avoid overwriting existing data (which `Map` will absolutely allow!):

{% embed https://gist.github.com/DuncanMcArdle/187529a6db4cb714194740de28e483d7 %}

## Set

Now that we’ve discussed `Map` , `Set` is actually super-simple. Think of `Set` as being a `Map` without the keys. So all values, no keys. Simple!

{% embed https://gist.github.com/DuncanMcArdle/bebe172e9c9ec210e52d5b028491f67c %}

### Duplication in a Set

The beauty of this is that it’s a very straightforward interface for dumping data that will retain its insertion order. But one really powerful aspect is that it will not allow data to be non-unique. This means that if you have a 10,000 item data set, and you insert it all into a `Set`, what you’ll be left with will all be unique. In addition, `Set` does (like `Map`) implement `.has()` , but this time around you’ll be checking if the `Set` has a _value_, rather than checking if a `Map` has a _key_.

{% embed https://gist.github.com/DuncanMcArdle/23e59123c283454899de85637894ad9e %}

If you’re suddenly thinking back to the last time you did a coding challenge, and realising this would have been super helpful, don’t worry, we’ve all been there.

### Looping through a Set

Just like with `Map`, `Set` has a number of helpful methods for iteration. You can use `Set.keys()` , `Set.values()` and `Set.entries()` , as well as the classic `Set.forEach()` . Though if you’re sitting there thinking “Wait, what keys, and what entries?”, you’d be right. In order to keep `Map` and `Set` close together in terms of spec, these additional functions have been provided, but in reality, they all return the same thing (or in some cases, two versions of the same thing!):

{% embed https://gist.github.com/DuncanMcArdle/4da5a88a54e49ff3afdd0b216d4eeaaf %}

## Communal functionality ( .clear() and .delete() )

In addition to the communal functionality and similarities already listed, both `Map` and `Set` also implement `clear()` (which will completely empty out the contents) and `delete()` (which will remove a specific entry (by key for `Map` and by value for `Set`)).

{% embed https://gist.github.com/DuncanMcArdle/7c8ab87b95b24e338ce782528498429b %}

## When to use Map & Set

Now that you know _how_ to use these wonderful data structures, you might be wondering _when_ to use them. Well the simple answer is: for data-sets (as the name suggests).

For `Map` , the power of `.get()` is truly incredible. Being able to dump massive amounts of data into a `Map` and then be able to call upon the entry you need without looping is incredibly useful, and comes without the overhead and complexities of the classic Object.

For `Set`, my personal favourite feature (and one I alluded to earlier) is being able to guarantee a unique set of data. This is logic that would normally be difficult and time consuming, but `Set` just… does it!

As with all of these modern constructs, it’s all about using the right tool for the job, so I hope now that you’ve read this article, you’ll feel just a little bit better equipped to make that decision.