From 9593450959e1eb43960b47895a7c1c84117cf532 Mon Sep 17 00:00:00 2001 From: wureny Date: Tue, 9 Jan 2024 13:11:44 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9Emapi.Len()=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mapx/builtin_map.go | 4 +++ mapx/builtin_map_test.go | 36 +++++++++++++++++++ mapx/hashmap.go | 4 +++ mapx/hashmap_test.go | 71 ++++++++++++++++++++++++++++++++++++ mapx/linkedmap.go | 4 +++ mapx/linkedmap_test.go | 36 +++++++++++++++++++ mapx/multi_map.go | 5 +++ mapx/multi_map_test.go | 78 ++++++++++++++++++++++++++++++++++++++++ mapx/treemap.go | 5 +++ mapx/treemap_test.go | 36 +++++++++++++++++++ mapx/types.go | 2 ++ 11 files changed, 281 insertions(+) diff --git a/mapx/builtin_map.go b/mapx/builtin_map.go index a5621d1e..c8484581 100644 --- a/mapx/builtin_map.go +++ b/mapx/builtin_map.go @@ -50,3 +50,7 @@ func newBuiltinMap[K comparable, V any](capacity int) *builtinMap[K, V] { data: make(map[K]V, capacity), } } + +func (b *builtinMap[K, V]) Len() int64 { + return int64(len(b.data)) +} diff --git a/mapx/builtin_map_test.go b/mapx/builtin_map_test.go index 63572e66..1cbfe26c 100644 --- a/mapx/builtin_map_test.go +++ b/mapx/builtin_map_test.go @@ -210,6 +210,42 @@ func TestBuiltinMap_Values(t *testing.T) { } } +func TestBuiltinMap_Len(t *testing.T) { + testCases := []struct { + name string + data map[string]string + + wantLen int64 + }{ + { + name: "got len", + data: map[string]string{ + "key1": "val1", + "key2": "val2", + "key3": "val3", + "key4": "val4", + }, + wantLen: 4, + }, + { + name: "empty map", + data: map[string]string{}, + wantLen: 0, + }, + { + name: "nil map", + wantLen: 0, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + m := builtinMapOf[string, string](tc.data) + assert.Equal(t, tc.wantLen, m.Len()) + }) + } +} + func builtinMapOf[K comparable, V any](data map[K]V) *builtinMap[K, V] { return &builtinMap[K, V]{data: data} } diff --git a/mapx/hashmap.go b/mapx/hashmap.go index f2a7a6a5..01ea17dc 100644 --- a/mapx/hashmap.go +++ b/mapx/hashmap.go @@ -158,3 +158,7 @@ func (n *node[T, ValType]) formatting() { n.value = val n.next = nil } + +func (m *HashMap[T, ValType]) Len() int64 { + return int64(len(m.hashmap)) +} diff --git a/mapx/hashmap_test.go b/mapx/hashmap_test.go index 51161644..ef4aabf3 100644 --- a/mapx/hashmap_test.go +++ b/mapx/hashmap_test.go @@ -469,6 +469,77 @@ func TestHashMap_Keys_Values(t *testing.T) { } } +func TestHashMap_Len(t *testing.T) { + testCases := []struct { + name string + genHashMap func() *HashMap[testData, int] + wantLen int64 + }{ + { + name: "empty", + genHashMap: func() *HashMap[testData, int] { + return NewHashMap[testData, int](10) + }, + wantLen: 0, + }, + { + name: "single key", + genHashMap: func() *HashMap[testData, int] { + testHashMap := NewHashMap[testData, int](10) + err := testHashMap.Put(newTestData(1), 1) + require.NoError(t, err) + return testHashMap + }, + wantLen: 1, + }, + { + name: "multiple keys", + genHashMap: func() *HashMap[testData, int] { + testHashMap := NewHashMap[testData, int](10) + for _, val := range []int{1, 2} { + err := testHashMap.Put(newTestData(val), val) + require.NoError(t, err) + } + return testHashMap + }, + wantLen: 2, + }, + { + name: "same key", + genHashMap: func() *HashMap[testData, int] { + testHashMap := NewHashMap[testData, int](10) + err := testHashMap.Put(newTestData(1), 1) + require.NoError(t, err) + // 验证id相同,覆盖的场景 + err = testHashMap.Put(newTestData(1), 11) + require.NoError(t, err) + return testHashMap + }, + wantLen: 1, + }, + { + name: "multi with same key", + genHashMap: func() *HashMap[testData, int] { + testHashMap := NewHashMap[testData, int](10) + for _, val := range []int{1, 2} { + // val为1、2 + err := testHashMap.Put(newTestData(val), val*10) + require.NoError(t, err) + } + err := testHashMap.Put(newTestData(1), 11) + require.NoError(t, err) + return testHashMap + }, + wantLen: 2, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + assert.Equal(t, tc.wantLen, tc.genHashMap().Len()) + }) + } +} + type testData struct { id int } diff --git a/mapx/linkedmap.go b/mapx/linkedmap.go index 127f32af..374dbf42 100644 --- a/mapx/linkedmap.go +++ b/mapx/linkedmap.go @@ -110,3 +110,7 @@ func (l *LinkedMap[K, V]) Values() []V { } return values } + +func (l *LinkedMap[K, V]) Len() int64 { + return int64(l.length) +} diff --git a/mapx/linkedmap_test.go b/mapx/linkedmap_test.go index a0060f3a..36e96a8b 100644 --- a/mapx/linkedmap_test.go +++ b/mapx/linkedmap_test.go @@ -467,3 +467,39 @@ func TestLinkedMap_PutAndDelete(t *testing.T) { }) } } + +func TestLinkedMap_Len(t *testing.T) { + testCases := []struct { + name string + linkedMap func(t *testing.T) *LinkedMap[int, int] + + wantLen int64 + }{ + { + name: "empty linked map", + linkedMap: func(t *testing.T) *LinkedMap[int, int] { + linkedTreeMap, _ := NewLinkedTreeMap[int, int](ekit.ComparatorRealNumber[int]) + return linkedTreeMap + }, + + wantLen: 0, + }, + { + name: "not empty linked map", + linkedMap: func(t *testing.T) *LinkedMap[int, int] { + linkedTreeMap, _ := NewLinkedTreeMap[int, int](ekit.ComparatorRealNumber[int]) + assert.NoError(t, linkedTreeMap.Put(1, 1)) + assert.NoError(t, linkedTreeMap.Put(2, 2)) + assert.NoError(t, linkedTreeMap.Put(3, 3)) + return linkedTreeMap + }, + + wantLen: 3, + }, + } + for _, tt := range testCases { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.wantLen, tt.linkedMap(t).Len()) + }) + } +} diff --git a/mapx/multi_map.go b/mapx/multi_map.go index f6497164..32668e05 100644 --- a/mapx/multi_map.go +++ b/mapx/multi_map.go @@ -93,3 +93,8 @@ func (m *MultiMap[K, V]) Values() [][]V { } return copyValues } + +// Len 返回 MultiMap 键值对的数量 +func (m *MultiMap[K, V]) Len() int64 { + return m.m.Len() +} diff --git a/mapx/multi_map_test.go b/mapx/multi_map_test.go index 0875763a..a81697ea 100644 --- a/mapx/multi_map_test.go +++ b/mapx/multi_map_test.go @@ -594,3 +594,81 @@ func TestMultiMap_PutMany(t *testing.T) { }) } } + +func TestMultiMap_Len(t *testing.T) { + testCases := []struct { + name string + multiTreeMap *MultiMap[int, int] + multiHashMap *MultiMap[testData, int] + wantLen int64 + }{ + { + name: "empty", + multiTreeMap: getMultiTreeMap(), + multiHashMap: getMultiHashMap(), + + wantLen: 0, + }, + { + name: "single", + multiTreeMap: func() *MultiMap[int, int] { + multiTreeMap := getMultiTreeMap() + _ = multiTreeMap.Put(1, 1) + return multiTreeMap + }(), + multiHashMap: func() *MultiMap[testData, int] { + multiHashMap := getMultiHashMap() + _ = multiHashMap.Put(testData{id: 1}, 1) + return multiHashMap + }(), + + wantLen: 1, + }, + { + name: "multiple", + multiTreeMap: func() *MultiMap[int, int] { + multiTreeMap := getMultiTreeMap() + _ = multiTreeMap.Put(1, 1) + _ = multiTreeMap.Put(2, 2) + _ = multiTreeMap.Put(3, 3) + return multiTreeMap + }(), + multiHashMap: func() *MultiMap[testData, int] { + multiHashMap := getMultiHashMap() + _ = multiHashMap.Put(testData{id: 1}, 1) + _ = multiHashMap.Put(testData{id: 2}, 2) + _ = multiHashMap.Put(testData{id: 3}, 3) + return multiHashMap + }(), + + wantLen: 3, + }, + { + name: "multiple with same key", + multiTreeMap: func() *MultiMap[int, int] { + multiTreeMap := getMultiTreeMap() + _ = multiTreeMap.Put(1, 1) + _ = multiTreeMap.Put(1, 2) + _ = multiTreeMap.Put(1, 3) + return multiTreeMap + }(), + multiHashMap: func() *MultiMap[testData, int] { + multiHashMap := getMultiHashMap() + _ = multiHashMap.Put(testData{id: 1}, 1) + _ = multiHashMap.Put(testData{id: 1}, 2) + _ = multiHashMap.Put(testData{id: 1}, 3) + return multiHashMap + }(), + wantLen: 1, + }, + } + for _, tt := range testCases { + t.Run("MultiTreeMap", func(t *testing.T) { + assert.Equal(t, tt.wantLen, tt.multiTreeMap.Len()) + }) + + t.Run("MultiHashMap", func(t *testing.T) { + assert.Equal(t, tt.wantLen, tt.multiHashMap.Len()) + }) + } +} diff --git a/mapx/treemap.go b/mapx/treemap.go index 719d696d..40f611fa 100644 --- a/mapx/treemap.go +++ b/mapx/treemap.go @@ -96,4 +96,9 @@ func (treeMap *TreeMap[T, V]) Values() []V { return vals } +// Len 返回了键值对的数量 +func (treeMap *TreeMap[T, V]) Len() int64 { + return int64(treeMap.tree.Size()) +} + var _ mapi[any, any] = (*TreeMap[any, any])(nil) diff --git a/mapx/treemap_test.go b/mapx/treemap_test.go index 378000fd..c224631a 100644 --- a/mapx/treemap_test.go +++ b/mapx/treemap_test.go @@ -409,6 +409,42 @@ func TestTreeMap_Delete(t *testing.T) { } } +func TestTreeMap_Len(t *testing.T) { + var tests = []struct { + name string + m map[int]int + len int64 + }{ + { + name: "empty-TreeMap", + m: map[int]int{}, + len: 0, + }, + { + name: "find", + m: map[int]int{ + 1: 1, + 2: 2, + 0: 0, + 3: 3, + 5: 5, + 4: 4, + }, + len: 6, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + treeMap, _ := NewTreeMap[int, int](compare()) + for k, v := range tt.m { + err := treeMap.Put(k, v) + require.NoError(t, err) + } + assert.Equal(t, tt.len, treeMap.Len()) + }) + } +} + func compare() ekit.Comparator[int] { return ekit.ComparatorRealNumber[int] } diff --git a/mapx/types.go b/mapx/types.go index 8b43c7aa..88806fb0 100644 --- a/mapx/types.go +++ b/mapx/types.go @@ -29,4 +29,6 @@ type mapi[K any, V any] interface { // 注意,当你调用多次拿到的结果不一定相等 // 取决于具体实现 Values() []V + // 返回键值对数量 + Len() int64 }