一、简单数组实现
想要实现一个数组,首先需要明白,数组内需要什么方法
常见的有:
- 数组大小
- 获取数组元素
- 更改数组元素
- 清空数组
- 添加数组元素
- 格式化输出数组
- 等等........
既然是自定义数组,那么就要求可以存储多种多样的元素,例如:基础的数据类型,结构体,等等
面对这个要求,我们有两种方式,第一种是使用 interface{ } , 第二种则是使用 泛型 T any
1. 实现代码
这里我们使用第二种,话不多说,上代码:
package list
import (
"errors"
"fmt"
)
type List[T any] interface {
Size() int
Get(index int) (T, error)
Set(index int, value T) error
Insert(index int, value T) error
Delete(index int) error
Append(value T)
Clear()
String() string
// 迭代器
Iterator() Iterator[T]
}
type ArrayList[T any] struct {
dataStore []T
theSize int
}
func NewArrayList[T any](capSize int) List[T] {
if capSize <= 0 {
capSize = 10
}
list := new(ArrayList[T])
list.dataStore = make([]T, 0, capSize)
list.theSize = 0
// 后续还要加入扩缩容机制
return list
}
func (a *ArrayList[T]) Size() int {
return a.theSize
}
func (a *ArrayList[T]) Get(index int) (T, error) {
if index < 0 || index >= a.theSize {
var zero T
return zero, errors.New("索引越界")
}
return a.dataStore[index], nil
}
func (a *ArrayList[T]) Set(index int, value T) error {
if index < 0 || index >= a.theSize {
return errors.New("该索引不存在")
}
a.dataStore[index] = value
return nil
}
func (a *ArrayList[T]) Insert(index int, value T) error {
if index < 0 || index >= a.theSize {
return errors.New("该索引不存在")
}
// 扩容
a.Expand()
a.dataStore = a.dataStore[:a.theSize+1]
for i := a.theSize; i > index; i-- {
a.dataStore[i] = a.dataStore[i-1]
}
a.dataStore[index] = value
a.theSize++
return nil
}
// Expand 扩容
func (a *ArrayList[T]) Expand() {
if a.theSize >= cap(a.dataStore) {
// make中间参数若为0,则只是声明,不是实际已经给你开辟了这么多
list := make([]T, a.theSize*2, a.theSize*2)
copy(list, a.dataStore)
a.dataStore = list
}
}
func (a *ArrayList[T]) Delete(index int) error {
if index < 0 || index >= a.theSize {
return errors.New("该索引不存在")
}
a.dataStore = append(a.dataStore[:index], a.dataStore[index+1:]...)
a.theSize--
return nil
}
func (a *ArrayList[T]) Append(value T) {
a.dataStore = append(a.dataStore, value)
a.theSize++
}
func (a *ArrayList[T]) Clear() {
a.dataStore = make([]T, 0, 10)
a.theSize = 0
}
func (a *ArrayList[T]) String() string {
return fmt.Sprint(a.dataStore)
}
2. 注意事项
- 使用接口,防止用户直接使用我们 ArrayList 里的成员
- 保持依赖注入的风格,让用户自己决定需要多大的容量。
- 关于扩缩容机制,可以自己权衡,示例中默认选择2倍,如有需要可以使用字节,则机制更精准完善
- 功能还可继续完善,例如格式化部分,判断部分等等
二、数组迭代器实现
迭代器的意思是:一种用于遍历集合(如数组、列表、集合、映射等)中元素的抽象工具或方法。
1. 实现代码
package list
import (
"errors"
)
// Iterator 迭代器
type Iterator[T any] interface {
HasNext() bool
Next() (T, error)
Remove()
GetIndex() int
}
// Iterable 可迭代存放的接口
type Iterable[T any] interface {
Iterator() Iterator[T]
}
// ArrayListIterator 制作一个数组迭代器,使用指针来遍历访问数组,更方便
type ArrayListIterator[T any] struct {
list *ArrayList[T]
currentIndex int // 当前索引
}
func (a *ArrayList[T]) Iterator() Iterator[T] {
it := new(ArrayListIterator[T])
it.currentIndex = 0
it.list = a
return it
}
func (it *ArrayListIterator[T]) HasNext() bool {
return it.currentIndex < it.list.theSize
}
func (it *ArrayListIterator[T]) Next() (T, error) {
if !it.HasNext() {
var zero T
return zero, errors.New("没有下一个")
}
value, err := it.list.Get(it.currentIndex)
it.currentIndex++
return value, err
}
func (it *ArrayListIterator[T]) Remove() {
it.currentIndex--
it.list.Delete(it.currentIndex)
}
func (it *ArrayListIterator[T]) GetIndex() int {
return it.currentIndex
}
迭代器中的方法,大多是使用我们在自定义数组中已经实现好的方法,所以写起来比较简单快捷
迭代器提供了一个统一的接口来遍历集合中的元素,而不必关心集合的具体实现细节。
2. 注意事项
- 除了基础的顺序遍历方式,我们还可以自行定义其他遍历方式,例如:逆序遍历,从某个元素位置往后遍历 / 往前遍历,等等......