JavaScript で「キーと値のペアをまとめたい」「重複のないリストを作りたい」というとき、オブジェクトや配列でも書けますが、専用の Map と Set を使うとずっとスッキリ書けます。この記事では、Map と Set の基本的な使い方、オブジェクトや配列との違い、ループの回し方、そして配列との相互変換までを、コード例とともに解説します。連想配列のような処理や重複排除をきれいに書きたい初心者〜中級者の方が対象です。
目次
Map と Set は何のためにあるのか
Map(マップ)は「キーと値のペア」を順番に保持するコレクションです。オブジェクト({})と似ていますが、キーに文字列以外(数値・オブジェクト・関数など)も使え、要素数を size で簡単に取れるといった利点があります。
Set(セット)は「重複しない値の集まり」です。同じ値を追加しても1つしか保持されないため、配列から重複を取り除く用途で特によく使われます。どちらも ES2015(ES6)で追加された、モダンな JavaScript の標準機能です。
Map の基本的な使い方
new Map() で空のマップを作り、set() で値を追加、get() で取り出します。キーの有無は has()、削除は delete() で行います。
const stock = new Map();
stock.set("apple", 30); // キー "apple" に値 30 を登録
stock.set("banana", 12);
console.log(stock.get("apple")); // 30
console.log(stock.has("banana")); // true
console.log(stock.size); // 2(要素数)
stock.delete("banana"); // キーごと削除
console.log(stock.has("banana")); // false
初期値をまとめて渡したいときは、[キー, 値] の配列を並べた二次元配列をコンストラクタに渡します。
const colors = new Map([
["red", "#ff0000"],
["green", "#00ff00"],
["blue", "#0000ff"],
]);
console.log(colors.get("green")); // #00ff00
console.log(colors.size); // 3
Map の主なメソッド・プロパティ
よく使うものを表にまとめます。set() はマップ自身を返すので、map.set(a).set(b) のようにつなげて書ける点も覚えておくと便利です。
| メソッド/プロパティ | 説明 |
|---|---|
set(key, value) | キーと値を登録する(既存キーなら上書き) |
get(key) | キーに対応する値を取り出す(無ければ undefined) |
has(key) | キーが存在するかを true/false で返す |
delete(key) | 指定したキーの要素を削除する |
clear() | すべての要素を削除する |
size | 要素数(プロパティなので () は不要) |
Map とオブジェクトの違い
「キーと値ならオブジェクトでもいいのでは?」と思うかもしれません。多くの場面でオブジェクトで十分ですが、次のような違いがあるため、用途によって Map が向くことがあります。
| 観点 | Map | オブジェクト |
|---|---|---|
| キーの型 | 何でも使える(数値・オブジェクト等) | 文字列とシンボルに限られる |
| 要素数の取得 | size ですぐ取れる | Object.keys().length が必要 |
| 順序 | 追加した順序が保証される | 基本は追加順だが例外がある |
| 繰り返し | そのまま for...of で回せる | Object.entries() 等が必要 |
キーが文字列で固定の「設定値のまとまり」ならオブジェクト、キーが動的に増減したり数値・オブジェクトをキーにしたいなら Map、と考えると選びやすいです。
Map をループで回す
Map は for...of でそのまま繰り返せます。各要素は [キー, 値] の形なので、分割代入で受け取ると読みやすくなります。forEach() も使えますが、引数の順番が (値, キー) である点に注意してください。
const stock = new Map([
["apple", 30],
["banana", 12],
]);
// for...of で [キー, 値] を分割代入
for (const [name, count] of stock) {
console.log(`${name}: ${count}個`);
}
// apple: 30個
// banana: 12個
// キーだけ・値だけが欲しいとき
console.log([...stock.keys()]); // ["apple", "banana"]
console.log([...stock.values()]); // [30, 12]
Set の基本的な使い方
Set は add() で値を追加し、has() で存在確認、delete() で削除します。同じ値を何度 add() しても、保持されるのは1つだけです。
const tags = new Set();
tags.add("css");
tags.add("js");
tags.add("css"); // 既にあるので追加されない
console.log(tags.has("js")); // true
console.log(tags.size); // 2("css" は1つだけ)
tags.delete("js");
console.log([...tags]); // ["css"]
Set で配列の重複を取り除く
Set の最もよく使う用途が、配列の重複排除です。配列を new Set() に渡すと重複が自動で消え、スプレッド構文 [...set] で配列に戻せます。1行で書けるのが魅力です。
const numbers = [1, 2, 2, 3, 3, 3, 4];
// Set に通してから配列に戻すと重複が消える
const unique = [...new Set(numbers)];
console.log(unique); // [1, 2, 3, 4]
同じ値かどうかは「厳密等価(===)」に近い比較で判定されます。そのため文字列の "1" と数値の 1 は別物として扱われ、両方残ります。重複排除の前に型をそろえておくと、意図しない残り方を防げます。
思った通りに重複が消えないとき
オブジェクトの配列は重複が消えない
Set はオブジェクトを「同じ中身か」ではなく「同じ参照か」で比較します。そのため {id: 1} が2つあっても、別々に作られたオブジェクトなら重複とは見なされず、両方残ります。オブジェクトの配列から重複を消したいときは、id など特定のキーを基準に Map でまとめ直すのが定番です。
const users = [
{ id: 1, name: "佐藤" },
{ id: 2, name: "鈴木" },
{ id: 1, name: "佐藤" }, // id が重複
];
// id をキーにした Map にまとめると、後勝ちで1件になる
const map = new Map(users.map((u) => [u.id, u]));
const unique = [...map.values()];
console.log(unique.length); // 2
size を length と書いてしまう
Map と Set の要素数は size プロパティです。配列の感覚で .length と書くと undefined になります。要素数が欲しいときは size、と覚えておきましょう。
まとめ
Map と Set は、キーと値の管理や重複排除をシンプルに書くための便利なコレクションです。要点を振り返ります。
Mapはset()/get()/has()でキーと値を扱い、要素数はsize- キーに文字列以外を使いたい・要素数や順序が重要なら
Mapが向く Setは重複しない値の集まり。[...new Set(配列)]で重複排除できる- オブジェクトの配列は参照で比較されるため、
Mapでキーを基準にまとめる
まずは配列の重複排除で Set を、設定値や集計で Map を使ってみると、その手軽さを実感できるはずです。