Skip to content

Commit

Permalink
对pr#63进行代码优化
Browse files Browse the repository at this point in the history
  • Loading branch information
mousseqin committed Sep 1, 2022
1 parent 11bed82 commit 4f8f4ff
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 34 deletions.
4 changes: 3 additions & 1 deletion .CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
[ekit: 修复 Pool TestPool](https://github.com/gotomicro/ekit/pull/40)
[ekit: 实现了 LinkedList Range](https://github.com/gotomicro/ekit/pull/46)
[ekit: 实现了 TaskPool](https://github.com/gotomicro/ekit/pull/57)
[ekit: 实现了 ArrayList Delete 方法缩容](https://github.com/gotomicro/ekit/pull/63)
- [ekit: add ToPtr function](https://github.com/gotomicro/ekit/pull/6)
- [sql: 支持 JsonColumn](https://github.com/gotomicro/ekit/pull/7)
- [bean/copier: 实现了基于反射的 ReflectCopier](https://github.com/gotomicro/ekit/pull/47)
Expand All @@ -28,4 +29,5 @@
- [Range](https://github.com/gotomicro/ekit/pull/46)
- [pool: 修复 Pool TestPool 测试不稳定的问题](https://github.com/gotomicro/ekit/pull/40)
- [ekit:引入 golangci-lint 和 goimports](https://github.com/gotomicro/ekit/pull/54)
- [ekit: 实现了 TaskPool](https://github.com/gotomicro/ekit/pull/57)
- [ekit: 实现了 TaskPool](https://github.com/gotomicro/ekit/pull/57)
- [ekit: 实现了 ArrayList Delete 方法缩容](https://github.com/gotomicro/ekit/pull/63)
18 changes: 6 additions & 12 deletions list/array_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,37 +86,31 @@ func (a *ArrayList[T]) Delete(index int) (T, error) {
}
}
a.vals = a.vals[:j]
if a.Cap() > 64 {
a.arrShrinkage()
}
a.shrink()
return res, nil
}

// arrShrinkage 数组缩容
func (a *ArrayList[T]) arrShrinkage() {
func (a *ArrayList[T]) shrink() {
var newCap int
c, l := a.Cap(), a.Len()
if c <= 64 {
return
}
// 如果当前容量 > 2048,元素是容量的 1/2的时候缩容
if c > 2048 && (c/l >= 2) {
// 缩到已有容量的 5/8
newCap = int(float32(c) * float32(0.625))
} else if c <= 2048 && (c/l >= 4) { // 如果当前容量 <=2048,元素是容量的四分之一的时候缩容
// 缩到原本的一半
} else if c <= 2048 && (c/l >= 4) {
newCap = c / 2
// 当容量小于64的时候,不需要继续缩容了
if newCap < 64 {
newCap = 64
}
} else {
// 不满足缩容
return
}
newList := NewArrayList[T](newCap)
_ = newList.Append(a.vals...)
a.vals = newList.vals
newSlice := make([]T, 0, newCap)
newSlice = append(newSlice, a.vals...)
a.vals = newSlice
}

func (a *ArrayList[T]) Len() int {
Expand Down
140 changes: 119 additions & 21 deletions list/array_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,31 +272,129 @@ func TestArrayList_Delete(t *testing.T) {
}

// TestArrayList_Delete_Shrinkage 测试缩容
func TestArrayList_Delete_Shrinkage(t *testing.T) {
// case : cap大于2048,元素是容量的 1/2。 target:已有容量的 5/8
list := NewArrayList[int](4000)
for i := 0; i < 999; i++ {
_ = list.Append(i)
}
_, _ = list.Delete(0)
assert.Equal(t, int(4000*0.625), list.Cap())
func TestArrayList_Delete_Shrink(t *testing.T) {
testCases := []struct {
name string // 用例名称
cap int // 原始容量
loop int // 切片中元素个数
wantCap int // 期望缩容后的容量
}{
// ----- #阶段一 逻辑测试# -----
// 只测试需求的逻辑和代码的逻辑是否一致

// case : cap小于等于2048,元素是容量的四分之一。 target:缩到原本的一半
list = NewArrayList[int](2048)
for i := 0; i < 300; i++ {
_ = list.Append(i)
// case 1: cap小于等于64,不进行缩容
{
name: "case 1",
cap: 64,
loop: 1,
wantCap: 64,
},
// case 2: cap大于2048,元素是容量的 1/2。 target:已有容量的 5/8
{
name: "case 2",
cap: 4000,
loop: 999,
wantCap: 2500,
},
// case 3: cap小于等于2048,元素是容量的四分之一。 target:缩到原本的一半
{
name: "case 3",
cap: 2048,
loop: 300,
wantCap: 1024,
},
// case 4: cap > 2048,但不满足缩容条件的例子
{
name: "case 4",
cap: 4000,
loop: 3888,
wantCap: 4000,
},
// case 5: cap <= 2048,但不满足缩容条件的例子
{
name: "case 5",
cap: 2048,
loop: 666,
wantCap: 2048,
},

// ----- #阶段二 边界测试# -----
// 测试用例边界
// ps:测试时:
// (1)会默认删除一个元素,loop需要+1
// (2)测试结果向下取整

// case 6: cap65
{
name: "case 6",
cap: 65,
loop: 2,
wantCap: 64,
},
// case 6-2: cap65,loop为16
{
name: "case 6-2",
cap: 65,
loop: 16,
wantCap: 64,
},
// case 6-3: cap130,loop为34,删除一个元素后为33,刚好不满足四分之一
{
name: "case 6-3",
cap: 130,
loop: 34,
wantCap: 130,
},
// case 7 cap2047
{
name: "case 7",
cap: 2047,
loop: 10,
wantCap: 1023, // 1023.5 ,向下取整
},
{
name: "case 7-1",
cap: 2047,
loop: 512,
wantCap: 1023,
},
{
name: "case 7-2",
cap: 2047,
loop: 513, // 四分之一为511.75,513删除一个元素512刚好不满足
wantCap: 2047,
},
// case 8 : cap 2049
{
name: "case 8",
cap: 2049,
loop: 10,
wantCap: 1280, // 1280.625 ,向下取整
},
{
name: "case 8-1",
cap: 2049,
loop: 1025,
wantCap: 1280, // 1280.625 ,向下取整
},
{
name: "case 8-2",
cap: 2049,
loop: 1026, // 二分之一为1024,1026删除一个元素后1025刚好不满足
wantCap: 2049,
},
}
_, _ = list.Delete(0)
assert.Equal(t, int(2048*0.5), list.Cap())

// case : cap小于等于2048,元素是容量的四分之一。 target:缩到原本的一半
// ps:当容量小于64的时候,容量为64
list = NewArrayList[int](100)
for i := 0; i < 10; i++ {
_ = list.Append(i)
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
list := NewArrayList[int](tc.cap)
for i := 0; i < tc.loop; i++ {
_ = list.Append(i)
}
_, _ = list.Delete(0)
assert.Equal(t, tc.wantCap, list.Cap())
})
}
_, _ = list.Delete(0)
assert.Equal(t, 64, list.Cap())
}

func TestArrayList_Len(t *testing.T) {
Expand Down

0 comments on commit 4f8f4ff

Please sign in to comment.