develop/Flutter

Dart에서 맵(map) 다루기

방뎁 2024. 11. 11. 15:03

Dart의 Map은 키-값 쌍을 저장하고 관리하는 강력한 컬렉션 타입입니다.


각 키에 대해 고유한 값을 저장하며,

데이터에 빠르게 접근하거나

수정할 수 있는 다양한 메서드와 속성을 제공합니다.

1. Map의 기본 개념

Map은 키와 값으로 구성된 데이터를 저장하는 자료 구조로, 각 키는 고유해야 합니다.
키를 통해 데이터를 쉽게 조회하고 수정할 수 있습니다.

Dart에서는 Map을 주로 JSON 데이터 처리나 키-값 형태의 데이터 저장 및 관리에 사용합니다.
예를 들어, 학생들의 성적이나 상품의 이름과 가격을 저장할 때 유용하게 활용할 수 있습니다.

Map 생성 Dart에서는 여러 방법으로 Map을 생성할 수 있습니다.
가장 일반적인 방법은 리터럴 문법이나 생성자를 사용하는 것입니다.

void main() { 
    // 리터럴을 사용한 Map 생성 
    Map<String, int> scores = {'John': 90, 'Emma': 85, 'Alex': 88}; // 생성자를 사용한 Map 생성 
    Map<String, int> ages = Map(); 
    ages['John'] = 25; ages['Emma'] = 30; 
    print(scores); // {John: 90, Emma: 85, Alex: 88} 
    print(ages); // {John: 25, Emma: 30}
} 

2. 기본 메서드와 사용법

Map 클래스는 데이터를 추가, 수정, 삭제, 조회하는 데 유용한 다양한 메서드를 제공합니다.

2.1 addAll

addAll 메서드는 다른 Map의 모든 키-값 쌍을 현재 Map에 추가합니다.

void main() { 
    Map<String, int> scores = {'John': 90, 'Emma': 85}; 
    Map<String, int> newScores = {'Alex': 88, 'Linda': 92}; 
    scores.addAll(newScores); 
    print(scores); 
    // {John: 90, Emma: 85, Alex: 88, Linda: 92}
} 

2.2 remove

remove 메서드는 지정한 키를 삭제하고, 해당 키에 연결된 값을 반환합니다.

void main() { 
    Map<String, int> scores = {'John': 90, 'Emma': 85, 'Alex': 88}; 
    scores.remove('Emma'); 
    print(scores); 
    // {John: 90, Alex: 88}
} 

2.3 containsKey, containsValue

containsKey 메서드는 Map에 특정 키가 존재하는지 확인하고,
containsValue는 특정 값이 존재하는지 확인합니다.

void main() { 
    Map<String, int> scores = {'John': 90, 'Emma': 85}; 
    print(scores.containsKey('John')); // true 
    print(scores.containsValue(100)); // false
} 

2.4 forEach

forEach 메서드는 Map의 각 키-값 쌍에 대해 특정 작업을 수행할 때 유용합니다.

void main() { 
    Map<String, int> scores = {'John': 90, 'Emma': 85, 'Alex': 88}; 
    scores.forEach((key, value) { 
        print('$key: $value'); 
    }); 
    // 출력: // John: 90 // Emma: 85 // Alex: 88 
}

2.5 map

map 메서드는 새로운 Map을 생성할 때 사용됩니다.
forEach와는 달리, 각 요소를 변경하고 그 결과를 활용하여 새로운 Map을 만들 수 있습니다.

void main() { 
    Map<String, int> scores = {'John': 90, 'Emma': 85, 'Alex': 88}; 
    Map<String, String> result = scores.map((key, value) => MapEntry(key, '$value points')); 
    print(result); // {John: 90 points, Emma: 85 points, Alex: 88 points}
} 

3. 고급 사용법

Dart의 Map 클래스는 기본 메서드 외에도 다양한 고급 기능과 메서드를 제공합니다.
이러한 기능들을 활용하면 더욱 효율적인 데이터 처리가 가능합니다.

3.1 entries 속성을 사용한 키-값 쌍 접근

entries 속성을 사용하면 MapEntry 객체를 통해 키와 값에 동시에 접근할 수 있습니다.

void main() { 
    Map<String, int> scores = {'John': 90, 'Emma': 85, 'Alex': 88}; 
    for (var entry in scores.entries) { 
        print('${entry.key}: ${entry.value}'); 
    } 
    // 출력: // John: 90 // Emma: 85 // Alex: 88 
}

3.2 update 메서드로 값 변경

update 메서드는 특정 키의 값을 조건에 따라 쉽게 변경할 수 있는 유용한 도구입니다.
값이 존재하지 않을 경우 추가 값을 설정하는 옵션도 제공합니다.

void main() { 
    Map<String, int> scores = {'John': 90, 'Emma': 85}; 
    scores.update('Emma', (value) => value + 5); 
    scores.update('Alex', (value) => 88, ifAbsent: () => 88); 
    print(scores);  // {John: 90, Emma: 90, Alex: 88}
} 

3.3 removeWhere

removeWhere 메서드를 사용하면 특정 조건에 맞는 키-값 쌍을 한 번에 삭제할 수 있습니다.

void main() { 
    Map<String, int> scores = {'John': 90, 'Emma': 85, 'Alex': 88}; 
    scores.removeWhere((key, value) => value < 90); 
    print(scores); // {John: 90, Alex: 88}
} 

3.4 map을 활용한 값 변환

앞서 소개한 map 메서드를 활용하면 특정 조건에 맞게 값을 변환하여 새로운 Map을 쉽게 생성할 수 있습니다.
** 개발에서 정말 많이 쓰임**

void main() { 
    Map<String, int> scores = {'John': 90, 'Emma': 85, 'Alex': 88}; 
    Map<String, int> doubledScores = scores.map((key, value) => MapEntry(key, value * 2)); 
    print(doubledScores); // {John: 180, Emma: 170, Alex: 176}
} 

4. Map 활용 팁과 성능 최적화

Dart의 Map은 효율적인 데이터 관리가 가능한 자료 구조이지만,
상황에 따라 성능이 크게 달라질 수 있습니다.

예를 들어,
대량의 데이터를 다룰 때
removeWhere나
forEach 메서드를 사용할 경우 성능에 주의해야 합니다. (노답발생 가능)

Map에 많은 키-값 쌍을 추가해야 할 때는 초기 생성 시 용량을 미리 설정하거나
addAll을 사용하여 한 번에 추가하는 것이 성능 면에서 유리할 수 있습니다.
상황마다 다르기 떄문에 성능 테스트가 필요할 수 있습니다.

뭐가 되었든 기초 map 함수를 잘 사용하면 코드의 질을 향상시키고
가독성을 높일 수 있습니다.