[Dart] Map 구현체: HashMap, SplayTreeMap, LinkedHashMap
![[Dart] Map 구현체: HashMap, SplayTreeMap, LinkedHashMap](/_next/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1705634462417%2Fd4e19977-81f0-4105-82f9-188266ebc9a1.png&w=3840&q=75)
Search for a command to run...
![[Dart] Map 구현체: HashMap, SplayTreeMap, LinkedHashMap](/_next/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1705634462417%2Fd4e19977-81f0-4105-82f9-188266ebc9a1.png&w=3840&q=75)
No comments yet. Be the first to comment.
한강 위 세빛둥둥섬에서의 11시간

개발자라면 누구나 한 번쯤 오픈소스 기여에 대한 환상을 가져본 적 있을 거다. 하지만 막상 시작하려면 어디서부터 해야 할지 막막하고, 괜히 대단한 걸 해야 할 것 같은 부담감에 선뜻 시작하기는 어려운 것 같다. 나 또한 해보고 싶다는 마음만 가지고 계속 미뤄왔다. 그러다 2025년 말 쯤에 오픈채팅방과 글또 슬랙 채널에서 "오픈소스 기여모임" 10기 모집글을 봤다. 2년 넘게 500명 이상의 참가자와 함께 1000개 이상의 PR을 만들어온 커뮤...
들어가며 드디어 글또 10기 활동 회고를 정리해본다.6개월간의 여정을 뒤돌아보니 정말 많은 일들이 있었다. 글또라는 커뮤니티를 8기가 한창 진행되고 있을 때 알았는데 이름부터 인상이 강렬했다. "글쓰는 또라이가 세상을 바꾼다." 유쾌하고 독특한 문구에 피식 웃으며, '여긴 도대체 어떤 사람들이 모이는 곳이지?' 하고 넘겼었다. 재밌는 건 결국, 나도 그 "또라이들" 중 한 명이 되었다는 것이다. 😌 글또는 개발자들이 2주에 한 번 글을 ...

들어가며 배포 직후, 환경변수가 제대로 설정되지 않아 여러 API가 제대로 작동하지 않는 일이 있었습니다. 다행히 밤에 사용자가 없을 때 문제가 있었던 거라 영향도는 크지 않았지만 앞으로도 계속해서 발생할 수 있는 문제이기 때문에 해결해야 겠다고 생각했습니다. 개발 단계에서 문제가 발견되면 가장 좋겠지만, 현재 팀 상황에서는 백엔드 개발을 혼자 담당하고 있어 코드 리뷰나 검증 프로세스를 갖추기가 쉽지 않았습니다. 그래서 최소한 배포 전에 자동으...
이 글에서 다루는 내용 포트포워딩이 안 되는 이유 (CGNAT 환경 이해) CGNAT 우회 방법들의 장단점 비교 Cloudflare Tunnel 설정 방법 (MacOS 기준) 외부에서 내 PC로 접근할 수 있도록 허용하는 방법을 생각하면 포트포워딩이 가장 먼저 떠오릅니다. 공유기에서 특정 포트를 열어 외부에서 서버에 접속할 수 있도록 설정하는 방식으로, 마인크래프트 멀티를 해보셨던 분이라면 분명 해보셨을 방법입니다. 😊 작년에 저는 홈서...

Flutter 개발을 하다가 key를 기준으로 정렬되는 map 자료형이 필요하여 공부를 찾아보다가 생각보다 여러 가지 구현체가 있다는 것을 알게 됐다. Dart 언어를 접한 지 벌써 3년이 다 되어가는데 이런 요구사항이 있었던 적이 한 번도 없었어서 이제야 알게 됐다는 것이 놀라웠다.
그래서 오늘은 세 가지 Dart Map 구현체 HashMap, SplayTreeMap, LinkedHashMap에 대해서 살펴보고 각 구현체를 언제 사용해야 하는지에 대해서 정리를 해보려고 한다.
Map은 연관된 키를 사용하여 값을 검색하는 키/값 쌍의 컬렉션이다. 여러 프로그래밍 언어에서 기본적으로 제공하는 자료형으로 파이썬에서는 사전(dictionary)이라는 자료형으로 제공하고 있다.
Map.entries 속성을 통해서 Map안의 키/값 쌍을 반복할 수 있는데 이때 반복의 순서는 맵의 세부 구현에 따라서 달라지게 된다. 현재 Dart 3.2.5 버전의 Map 구현체는 HashMap, SplayTreeMap, LinkedHashMap 세 가지가 있다.
HashMap은 Dart의 기본 Map 구현체로 해시 테이블을 활용하여 조회, 추가, 삭제가 빠르지만 요소의 순서를 유지하지 않는다는 특징이 있다.
HashMap이 적합한 상황성능: 빠른 조회, 추가, 삭제가 중요할 때
순서가 없는 데이터: 요소들의 순서가 중요하지 않은 상황
import 'dart:collection';
void main() {
final userPreferences = HashMap<String, dynamic>();
// 사용자 선호도 설정
userPreferences['theme'] = 'Dark';
userPreferences['fontSize'] = 14;
userPreferences['notificationsEnabled'] = true;
// 특정 선호도 접근
final theme = userPreferences['theme'];
print('사용자가 선택한 테마: $theme');
// 더 많은 선호도 추가
userPreferences['language'] = 'English';
}
// Output:
// 사용자가 선택한 테마: Dart
SplayTreeMap은 self-balancing binary search tree를 기반으로 하는 Map 구현체로 키를 기준으로 값을 정렬한다. 자주 사용하는 값은 트리의 루트에 가까운 위치로 이동되어 이후에 접근할 때 더 빠르게 접근할 수 있게 만든다는 특징이 있다.
SplayTreeMap이 적합한 상황정렬: 키를 기준으로 요소들을 정렬된 상태로 유지해야 할 때 (순서가 중요한 데이터)
효율적인 접근: 데이터별로 접근 빈도가 크게 차이나는 상황
점수 순으로 정렬된 상태를 유지하면서 Top3와 같이 자주 접근하는 데이터가 있을 경우가 있을 때 SplayTreeMap이 유용하게 사용될 수 있다.
import 'dart:collection';
void main() {
final scores = <String, int>{};
final leaderboard = SplayTreeMap<int, Set<String>>();
// 플레이어 점수 추가/업데이트하는 함수
void updateScore(String playerId, int score) {
leaderboard[scores[playerId]]?.remove(playerId);
leaderboard.putIfAbsent(score, () => {}).add(playerId);
scores[playerId] = score;
}
// 점수 추가/업데이트
updateScore('player1', 100);
updateScore('player2', 150);
updateScore('player3', 100);
// 리더보드를 내림차순으로 표시 (가장 높은 점수가 먼저)
for (var score in leaderboard.keys.toList().reversed) {
print('점수: $score, 플레이어들: ${leaderboard[score]}');
}
// 점수 추가/업데이트
updateScore('player1', 120);
updateScore('player2', 200);
updateScore('player3', 150);
// 리더보드를 내림차순으로 표시 (가장 높은 점수가 먼저)
print("\n업데이트 후");
for (var score in leaderboard.keys.toList().reversed) {
if(leaderboard[score] != null && leaderboard[score]!.isNotEmpty) {
print('점수: $score, 플레이어들: ${leaderboard[score]}');
}
}
}
// Output:
// 점수: 150, 플레이어들: {player2}
// 점수: 100, 플레이어들: {player1, player3}
//
// 업데이트 후
// 점수: 200, 플레이어들: {player2}
// 점수: 150, 플레이어들: {player3}
// 점수: 120, 플레이어들: {player1}
LinkedHashMap은 항목이 추가된 순서를 유지한다. 즉, 맵을 순회할 때 항목이 추가된 순서대로 반환된다. 항목의 삽입 순서가 중요할 때 특히 유용하다.
LinkedHashMap이 적합한 상황쇼핑카트에는 담은 순서대로 표시가 되며 쇼핑카트의 수량이 변경되더라도 그 순서는 변경되지 않는다. 쇼핑카트는 LinkedHashMap이 동작하는 방식과 유사하다.
import 'dart:collection';
void main() {
var shoppingCart = LinkedHashMap<String, int>();
// 상품을 쇼핑 카트에 추가
shoppingCart['Apple'] = 1;
shoppingCart['Banana'] = 2;
shoppingCart['Orange'] = 2;
// 카트 내용 확인
print("쇼핑 카트:");
shoppingCart.forEach((itemNumber, itemName) {
print("$itemNumber: $itemName개");
});
// 수량 변경
shoppingCart['Apple'] = 6;
print("\n수량 변경 후 쇼핑 카트:");
shoppingCart.forEach((itemNumber, itemName) {
print("$itemNumber: $itemName개");
});
}
// Output:
// 쇼핑 카트:
// Apple: 1개
// Banana: 2개
// Orange: 2개
//
// 수량 변경 후 쇼핑 카트:
// Apple: 6개
// Banana: 2개
// Orange: 2개
순서가 중요하지 않고 빠른 검색, 삽입, 삭제가 필요한 경우 HashMap
정렬과 자주 접근하는 요소에 대한 효율적인 접근이 필요할 때 SplayTreeMap
삽입 순서가 유지되어야 하는 경우 LinkedHashMap