Skip to content

Commit

Permalink
Implement GetElement method (#17)
Browse files Browse the repository at this point in the history
GetElement returns the element for a key. If the key does not exist, the
pointer will be nil.

Co-authored-by: Jyoti Shete <jyoti.shete@coursehero.com>
  • Loading branch information
jyotisj and Jyoti Shete committed Jul 8, 2020
1 parent de4adf9 commit 5498093
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 0 deletions.
16 changes: 16 additions & 0 deletions orderedmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,22 @@ func (m *OrderedMap) GetOrDefault(key, defaultValue interface{}) interface{} {
return defaultValue
}

// GetElement returns the element for a key. If the key does not exist, the
// pointer will be nil.
func (m *OrderedMap) GetElement(key interface{}) *Element {
value, ok := m.kv[key]
if ok {
element := value.Value.(*orderedMapElement)
return &Element{
element: value,
Key: element.key,
Value: element.value,
}
}

return nil
}

// Len returns the number of elements in the map.
func (m *OrderedMap) Len() int {
return len(m.kv)
Expand Down
117 changes: 117 additions & 0 deletions orderedmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,45 @@ func TestOrderedMap_Back(t *testing.T) {
})
}

func TestGetElement(t *testing.T) {
t.Run("ReturnsElementForKey", func(t *testing.T) {
m := orderedmap.NewOrderedMap()
m.Set("foo", "bar")

var results []interface{}
element := m.GetElement("foo")
if element != nil {
results = append(results, element.Key, element.Value)
}

assert.Equal(t, []interface{}{"foo", "bar"}, results)
})

t.Run("ElementForKeyDoesntExistOnNonEmptyMap", func(t *testing.T) {
m := orderedmap.NewOrderedMap()
m.Set("foo", "baz")
element := m.GetElement("bar")
assert.Nil(t, element)
})

t.Run("Performance", func(t *testing.T) {
if testing.Short() {
t.Skip("performance test skipped in short mode")
}

res1 := testing.Benchmark(benchmarkOrderedMap_GetElement(1))
res4 := testing.Benchmark(benchmarkOrderedMap_GetElement(4))

// O(1) would mean that res4 should take about the same time as res1,
// because we are accessing the same amount of elements, just on
// different sized maps.

assert.InDelta(t,
res1.NsPerOp(), res4.NsPerOp(),
0.5*float64(res1.NsPerOp()))
})
}

func benchmarkMap_Set(multiplier int) func(b *testing.B) {
return func(b *testing.B) {
m := make(map[int]bool)
Expand Down Expand Up @@ -364,6 +403,23 @@ func BenchmarkOrderedMap_Get(b *testing.B) {
benchmarkOrderedMap_Get(1)(b)
}

func benchmarkOrderedMap_GetElement(multiplier int) func(b *testing.B) {
m := orderedmap.NewOrderedMap()
for i := 0; i < 1000*multiplier; i++ {
m.Set(i, true)
}

return func(b *testing.B) {
for i := 0; i < b.N; i++ {
m.GetElement(i % 1000 * multiplier)
}
}
}

func BenchmarkOrderedMap_GetElement(b *testing.B) {
benchmarkOrderedMap_GetElement(1)(b)
}

var tempInt int

func benchmarkOrderedMap_Len(multiplier int) func(b *testing.B) {
Expand Down Expand Up @@ -535,6 +591,24 @@ func BenchmarkOrderedMapString_Get(b *testing.B) {
benchmarkOrderedMapString_Get(1)(b)
}

func benchmarkOrderedMapString_GetElement(multiplier int) func(b *testing.B) {
m := orderedmap.NewOrderedMap()
a := "12345678"
for i := 0; i < 1000*multiplier; i++ {
m.Set(a+strconv.Itoa(i), true)
}

return func(b *testing.B) {
for i := 0; i < b.N; i++ {
m.GetElement(a + strconv.Itoa(i%1000*multiplier))
}
}
}

func BenchmarkOrderedMapString_GetElement(b *testing.B) {
benchmarkOrderedMapString_GetElement(1)(b)
}

func benchmarkMapString_Delete(multiplier int) func(b *testing.B) {
return func(b *testing.B) {
m := make(map[string]bool)
Expand Down Expand Up @@ -711,6 +785,25 @@ func BenchmarkBigOrderedMap_Get(b *testing.B) {
benchmarkBigOrderedMap_Get()(b)
}

func benchmarkBigOrderedMap_GetElement() func(b *testing.B) {
m := orderedmap.NewOrderedMap()
for i := 0; i < 10000000; i++ {
m.Set(i, true)
}

return func(b *testing.B) {
for j := 0; j < b.N; j++ {
for i := 0; i < 10000000; i++ {
m.GetElement(i)
}
}
}
}

func BenchmarkBigOrderedMap_GetElement(b *testing.B) {
benchmarkBigOrderedMap_GetElement()(b)
}

func benchmarkBigMap_Iterate() func(b *testing.B) {
m := make(map[int]bool)
for i := 0; i < 10000000; i++ {
Expand Down Expand Up @@ -820,6 +913,26 @@ func BenchmarkBigOrderedMapString_Get(b *testing.B) {
benchmarkBigOrderedMapString_Get()(b)
}

func benchmarkBigOrderedMapString_GetElement() func(b *testing.B) {
m := orderedmap.NewOrderedMap()
a := "1234567"
for i := 0; i < 10000000; i++ {
m.Set(a+strconv.Itoa(i), true)
}

return func(b *testing.B) {
for j := 0; j < b.N; j++ {
for i := 0; i < 10000000; i++ {
m.GetElement(a + strconv.Itoa(i))
}
}
}
}

func BenchmarkBigOrderedMapString_GetElement(b *testing.B) {
benchmarkBigOrderedMapString_GetElement()(b)
}

func benchmarkBigMapString_Iterate() func(b *testing.B) {
m := make(map[string]bool)
a := "12345678"
Expand Down Expand Up @@ -866,6 +979,7 @@ func BenchmarkAll(b *testing.B) {
b.Run("BenchmarkMap_Set", BenchmarkMap_Set)
b.Run("BenchmarkOrderedMap_Get", BenchmarkOrderedMap_Get)
b.Run("BenchmarkMap_Get", BenchmarkMap_Get)
b.Run("BenchmarkOrderedMap_GetElement", BenchmarkOrderedMap_GetElement)
b.Run("BenchmarkOrderedMap_Delete", BenchmarkOrderedMap_Delete)
b.Run("BenchmarkMap_Delete", BenchmarkMap_Delete)
b.Run("BenchmarkOrderedMap_Iterate", BenchmarkOrderedMap_Iterate)
Expand All @@ -875,13 +989,15 @@ func BenchmarkAll(b *testing.B) {
b.Run("BenchmarkBigOrderedMap_Set", BenchmarkBigOrderedMap_Set)
b.Run("BenchmarkBigMap_Get", BenchmarkBigMap_Get)
b.Run("BenchmarkBigOrderedMap_Get", BenchmarkBigOrderedMap_Get)
b.Run("BenchmarkBigOrderedMap_GetElement", BenchmarkBigOrderedMap_GetElement)
b.Run("BenchmarkBigOrderedMap_Iterate", BenchmarkBigOrderedMap_Iterate)
b.Run("BenchmarkBigMap_Iterate", BenchmarkBigMap_Iterate)

b.Run("BenchmarkOrderedMapString_Set", BenchmarkOrderedMapString_Set)
b.Run("BenchmarkMapString_Set", BenchmarkMapString_Set)
b.Run("BenchmarkOrderedMapString_Get", BenchmarkOrderedMapString_Get)
b.Run("BenchmarkMapString_Get", BenchmarkMapString_Get)
b.Run("BenchmarkOrderedMapString_GetElement", BenchmarkOrderedMapString_GetElement)
b.Run("BenchmarkOrderedMapString_Delete", BenchmarkOrderedMapString_Delete)
b.Run("BenchmarkMapString_Delete", BenchmarkMapString_Delete)
b.Run("BenchmarkOrderedMapString_Iterate", BenchmarkOrderedMapString_Iterate)
Expand All @@ -891,6 +1007,7 @@ func BenchmarkAll(b *testing.B) {
b.Run("BenchmarkBigOrderedMapString_Set", BenchmarkBigOrderedMapString_Set)
b.Run("BenchmarkBigMapString_Get", BenchmarkBigMapString_Get)
b.Run("BenchmarkBigOrderedMapString_Get", BenchmarkBigOrderedMapString_Get)
b.Run("BenchmarkBigOrderedMapString_GetElement", BenchmarkBigOrderedMapString_GetElement)
b.Run("BenchmarkBigOrderedMapString_Iterate", BenchmarkBigOrderedMapString_Iterate)
b.Run("BenchmarkBigMapString_Iterate", BenchmarkBigMapString_Iterate)
}

0 comments on commit 5498093

Please sign in to comment.