Golang에서는 Set(집합) 자료구조를 직접 구현하여 사용하여야 합니다.
Set은 중복을 허용하지 않는 원소들의 모임이며, 멤버십 확인 및 집합 연산을 위해 자주 사용됩니다.
보통 Set 구현을 map[T]struct{}
와 map[T]bool
로 이용해서 합니다.
Set을 구현하는 두 가지 방식인 map[T]struct{}
와 map[T]bool
을 비교해보고자 합니다.
Map에 대한 내용은 아래 글에서 확인하시면 됩니다.
두 방식 모두 유효한 방법이지만, 각각의 특징을 이해하고 해당 상황에 적합한 방식을 선택하는 것이 중요합니다.
이제 더 자세한 내용을 살펴보겠습니다.
map[T]struct{}
방식
map[T]struct{}
방식은 Set을 구현하기 위해 맵(Map)을 사용하고 값(Value)으로는 빈 구조체(struct{}
)를 활용하는 방식입니다. 다음은 고려해야 할 주요 사항입니다:
메모리 효율성
값으로 struct{}
를 사용하는 것은 메모리 효율성을 보장합니다.
빈 구조체는 크기가 0이므로, 각 원소마다 추가적인 메모리가 낭비되지 않습니다.
이 방식은 특히 큰 Set이나 메모리 제약이 있는 환경에서 유리합니다.
키의 중요성 강조
map[T]struct{}
를 사용함으로써, Set에서는 키만이 중요하다는 사실을 강조할 수 있습니다.
빈 구조체는 정보를 담지 않기 때문에, 키 자체가 원소를 나타낸다는 점을 명확하게 표현할 수 있습니다.
이는 코드를 더 의미롭고 이해하기 쉽게 만들어줍니다.
예시
type Set struct {
data map[T]struct{}
}
func NewSet() *Set {
s := &Set{
data: make(map[T]struct{}),
}
return s
}
func (s *Set) Add(element T) {
s.data[element] = struct{}{}
}
func (s *Set) Remove(element T) {
delete(s.data, element)
}
func (s *Set) Contains(element T) bool {
_, exists := s.data[element]
return exists
}
func (s *Set) Size() int {
return len(s.data)
}
Set에 원소를 추가할 때는 해당 키에 빈 구조체를 할당하면 됩니다: set[element] = struct{}{}
Set 원소 포함 여부를 확인할 때는 맵에서 해당 키가 존재하는지 확인하면 됩니다:_, exists := set[element]
원소를 삭제할 때는 delete
함수를 사용하면 됩니다: delete(set, element)
map[T]bool
방식
map[T]bool
방식은 Set을 구현하기 위해 맵(Map)을 사용하며 값(Value)으로는 boolean 타입인 true
또는 false
를 활용합니다.
추가적인 메모리 사용
값으로 bool
을 사용하는 것은 각 원소마다 추가적인 메모리를 사용하게 됩니다.map[T]struct{}
방식에 비해 약간 더 많은 메모리를 사용하므로, 큰 Set을 다룰 때는 약간의 메모리 오버헤드가 발생할 수 있습니다.
추가 정보의 유연성:
map[T]bool
방식은 각 원소와 관련된 추가 정보를 연결할 수 있는 유연성을 제공합니다.
boolean 값 사용을 통해 원소와 관련된 보조 데이터를 저장하고 검색할 수 있습니다.
이는 원소별 속성이나 메타데이터가 필요한 경우에 유용할 수 있습니다.
예시
type Set struct {
data map[T]bool
}
func NewSet() *Set {
s := &Set{
data: make(map[T]bool),
}
return s
}
func (s *Set) Add(element T) {
s.data[element] = true
}
func (s *Set) Remove(element T) {
delete(s.data, element)
}
func (s *Set) Contains(element T) bool {
exists := s.data[element]
return exists
}
func (s *Set) Size() int {
return len(s.data)
}
원소를 Set에 추가하기 위해 해당 키에 true
값을 할당합니다: set[element] = true
.
Set 원소 포함 여부를 확인하기 위해서는 키에 연결된 boolean 값을 확인하면 됩니다: exists := set[element]
.
원소를 삭제하는 방법은 map[T]struct{}
방식과 유사합니다: delete(set, element)
를 사용하면 됩니다.
결론
Golang에서 Set을 구현할 때, map[T]struct{}
와 map[T]bool
방식은 모두 유효한 선택지입니다.
하지만 저는 주로 map[T]bool
방식보다는 map[T]struct{}
방식을 선호하는 편입니다.
참고
https://itnext.io/set-in-go-map-bool-and-map-struct-performance-comparison-5315b4b107b
https://www.reddit.com/r/golang/comments/qzha6o/for_sets_maptstruct_vs_maptbool/