This is my very first attempt at implementation the missing multimap
data structure for the Go language.
It's heavily inspired by Jason's Wangsadinata go-multimap.
The primary impetus, on the other hand, is that I come from programming in the Java language, where there is a Guava library with a multimap implementation.
Install the package via the following:
go get -u github.com/rafos/go-multimap
The go-multimap package can be used similarly to the following:
package main
import (
"fmt"
"github.com/rafos/go-multimap/slicemultimap"
)
func main() {
usPresidents := []struct {
firstName string
middleName string
lastName string
termStart int
termEnd int
}{
{"George", "", "Washington", 1789, 1797},
{"John", "", "Adams", 1797, 1801},
{"Thomas", "", "Jefferson", 1801, 1809},
{"James", "", "Madison", 1809, 1817},
{"James", "", "Monroe", 1817, 1825},
{"John", "Quincy", "Adams", 1825, 1829},
{"John", "", "Tyler", 1841, 1845},
{"James", "", "Polk", 1845, 1849},
{"Grover", "", "Cleveland", 1885, 1889},
{"Benjamin", "", "Harrison", 1889, 1893},
{"Grover", "", "Cleveland", 1893, 1897},
{"George", "Herbert Walker", "Bush", 1989, 1993},
{"George", "Walker", "Bush", 2001, 2009},
{"Barack", "Hussein", "Obama", 2009, 2017},
}
m := slicemultimap.New[string, string]()
for _, president := range usPresidents {
m.Put(president.firstName, president.lastName)
}
for _, firstName := range m.KeySet() {
lastNames, _ := m.Get(firstName)
fmt.Printf("%v: %v\n", firstName, lastNames)
}
}
Example output:
$ go run example/example.go
John: [Adams Adams Tyler]
Thomas: [Jefferson]
James: [Madison Monroe Polk]
Grover: [Cleveland Cleveland]
Benjamin: [Harrison]
Barack: [Obama]
George: [Washington Bush Bush]
To see the benchmark, run the following on each of the sub-packages:
go test -run=NO_TEST -bench . -benchmem -benchtime 1s ./...
goos: darwin goarch: amd64 pkg: github.com/rafos/go-multimap/slicemultimap cpu: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz BenchmarkMultiMapGet100-8 578694 2001 ns/op 0 B/op 0 allocs/op BenchmarkMultiMapGet1000-8 48384 24430 ns/op 0 B/op 0 allocs/op BenchmarkMultiMapGet10000-8 3927 315908 ns/op 0 B/op 0 allocs/op BenchmarkMultiMapGet100000-8 298 3822512 ns/op 0 B/op 0 allocs/op BenchmarkMultiMapPut100-8 209097 6214 ns/op 8590 B/op 0 allocs/op BenchmarkMultiMapPut1000-8 20220 64400 ns/op 84408 B/op 745 allocs/op BenchmarkMultiMapPut10000-8 1525 715396 ns/op 596457 B/op 9822 allocs/op BenchmarkMultiMapPut100000-8 128 10531982 ns/op 7172956 B/op 105994 allocs/op BenchmarkMultiMapPutAll100-8 224827 5502 ns/op 7989 B/op 0 allocs/op BenchmarkMultiMapPutAll1000-8 18633 67812 ns/op 91091 B/op 745 allocs/op BenchmarkMultiMapPutAll10000-8 1554 726543 ns/op 586781 B/op 9821 allocs/op BenchmarkMultiMapPutAll100000-8 128 10541793 ns/op 7172955 B/op 105994 allocs/op BenchmarkMultiMapRemove100-8 594860 1976 ns/op 0 B/op 0 allocs/op BenchmarkMultiMapRemove1000-8 41503 30151 ns/op 5952 B/op 744 allocs/op BenchmarkMultiMapRemove10000-8 2859 353375 ns/op 77952 B/op 9744 allocs/op BenchmarkMultiMapRemove100000-8 334 3206979 ns/op 797956 B/op 99744 allocs/op BenchmarkMultiMapRemoveAll100-8 1905345 630.3 ns/op 0 B/op 0 allocs/op BenchmarkMultiMapRemoveAll1000-8 187369 6343 ns/op 0 B/op 0 allocs/op BenchmarkMultiMapRemoveAll10000-8 18818 62743 ns/op 0 B/op 0 allocs/op BenchmarkMultiMapRemoveAll100000-8 1756 635113 ns/op 0 B/op 0 allocs/op PASS ok github.com/rafos/go-multimap/slicemultimap 30.781s