수강하고 있는 강의에서 백준 문제 중 18870번 좌표 압축 문제다뤄서 풀었는데 배열로 풀어서 메모리 초과가 났다. 결국 못 풀어서 강의를 봤는데 강의에서 Map으로 문제를 해결했는데 Object랑 비슷하게 쓰이는데 강의에서 처음 알게 되어서 차이를 공부하게 되었다.
Map 객체는 키-값 쌍인 집합으로 Map에서의 키는 오직 단 하나만 존재한다.
let myMap = new Map();
myMap.set('a', 1);
myMap.set('b', 2);
myMap.set('c', 3);
console.log(myMap.get('a')); // 1
myMap.set('a', 56);
console.log(myMap.get('a')); // 56
console.log(myMap.size); // 3
위 코드에서 알 수 있듯이 set()메소드를 통해서 Map객체에 키와 값을 추가할 수 있다.
또한, 키는 오직 단 하나로 값은 키에 다른 값을 넣었을 때는 나중에 넣은 값으로 저장된다.
그리고 get()메소드를 이용해서 주어진 키에 해당하는 값을 반환하거나 값이 없다면 undefined를 반환한다.
Object
Object의 키는 String 또는 Symbol이여야 하는데 주로 나는 String으로만 사용했었다.
const obj = {
name: "jigu",
email: "jseo9732@gmail.com",
age: 85,
};
console.log(obj.name); // jigu
console.log(obj["name"]); // jigu
Map
Map의 키는 모든 값(모든 타입(any) / 함수, 객체 또는 원시 값 포함)이 될 수 있다.
const func = () => {
console.log("Hi");
};
let myMap1= new Map();
myMap1.set("name", "jigu");
myMap1.set(func, "키가 함수임");
myMap1.set(100, "키가 숫자임");
console.log(myMap.get("name")); // jigu
console.log(myMap.get(func)); // 키가 함수임
console.log(myMap.get(100)); // 키가 숫자임
let myMap2 = new Map([
['id', 0],
['이름', '마이클'],
['전공', '영문학'],
['나이', 29],
]);
Object의 키는 정렬되어 있지만 항상 그런 것은 아니다. 그 동안 학습하기로도 객체는 for in문을 사용했을 떄도 우리가 생각하는 순서대로 나오지 않을 수 있다고 알고 있다.Map은 키와 값이 삽입한 순서대로 정렬된다. 따라서, for of문을 사용했을 떄도 순서대로 값을 얻을 수 있기 때문에 순서가 중요할 때는 Map을 사용해야한다.Object
Object는 length를 통해서 길이를 구할 수 없다. 길아를 구하기 위해서는 JavaScript에서 제공하는 정적 메소드인 Object.keys를 이용해야한다.
const obj = {
name: "jigu",
email: "jseo9732@gmail.com",
age: 85,
};
console.log(obj.length); // undefined
console.log(Object.keys(obj).length); // 3
Map
Map의 아이템 수는 비교적 쉽게 size 메소드를 통해 구할 수 있다.
let myMap = new Map();
myMap.set("name", "jigu");
myMap.set(func, "키가 함수임");
myMap.set(100, "키가 숫자임");
console.log(myMap.size); // 3
Object
for of문은 iterable한 객체((Array, Map, Set, String, TypedArray, arguments 객체 등을 포함)에서만 사용할 수 있는 문법으로 Object는 iterable하지 않기 때문에 직접 반복할 수 없다.
만약 Object에 반복문을 사용하고 싶다면 for in문을 사용해야한다.
const obj = {
name: "jigu",
email: "jseo9732@gmail.com",
age: 85,
};
for (const i of obj) {
console.log(i);
} // 타입 에러 발생
for (const i in obj) {
console.log(i);
}
// name
// email
// age
for (const i in obj) {
console.log(obj[i]);
}
// jigu
// jseo9732@gmail.com
// 85
Map
Map은 위에서 말한 것처럼 iterable한 객체이므로 for of문을 사용할 수 있다.
let myMap = new Map();
myMap.set("name", "jigu");
myMap.set(func, "키가 함수임");
myMap.set(100, "키가 숫자임");
for (const i of myMap) {
console.log(i);
}
// [ 'name', 'jigu' ]
// [ [Function: func], '키가 함수임' ]
// [ 100, '키가 숫자임' ]
Object
Object는 forEach를 지원하지 않는다.
Map
반면, Map은 내부에서 Iterator 인터페이스를 구현했기 때문에 forEach를 사용할 수 있다.
const func = () => {};
let myMap = new Map();
myMap.set("name", "jigu");
myMap.set(func, "키가 함수임");
myMap.set(100, "키가 숫자임");
myMap.forEach((value, key, map) => {
console.log(`${key}: ${value}`);
});
// name: jigu
// () => {}: 키가 함수임
// 100: 키가 숫자임
알고리즘 문제를 풀다가 알게 된 개념이라 Map의 시간 복잡도도 찾아보았다.
강의에서 객체가 아닌 Map으로 문제를 푼 이유가 시간 복잡도의 차이가 나서 안지 궁금했다.
| Object | Map | |
|---|---|---|
| 시간 복잡도 | O(1) | O(1) |
N개의 원소가 있는 Map과 Object의 값의 접근을 위한 시간 복잡도는 O(1)로 같다.
아마 강의에서 문제를 Map으로 푼 이유는 삽입된 순서대로 값이 정렬되기 위해서가 아닐까 추측해본다.
참조