前言
Java 内置了丰富的容器类,不同容器用于处理各种业务场景。 Go 虽然语言设计上和 Java 有很多相似的地方, 但原生并没有支持太多容器类的数据结构,只有 map 和 slice。标准库的 container
package 对容器数据结构做了扩展,支持堆(Heap)、链表(LinkedList) 和循环链表(Circular List)3个容器。
容器
熟悉 C++ 和 Java 对容器应该都有清晰的了解, 它是现代编程实践中不可或缺的一部分,具有多种形式, 一般被描述为具有操作容器内容的方法的对象。Go 提供的基本容器主要有6个:
-
内置容器:
-
map: 关联容器
-
slice: 动态扩容的顺序容器
-
-
channels:队列
-
container标准库(
pkg/container
):- list:链表容器
- ring:循环链表容器
- heap: 堆容器,提供 heap 的实现
slice 、map 和 channel 是 Go 最常见、也是内置的容器数据结构,其他容器都在标准库的 container
包下。在使用 container
三个容器的时候,不必再费心实现数据结构相关的算法。同时,因为container
提供的容器支持的入参类型都是 interface{}
, 所以只要实现了容器的 interface
, 就可以处理任何类型的值。
container/list
链表容器 list 的代码是一个双向链表的实现。list 维护两个结构体:Element 和 List:
// Element is an element of a linked list.
type Element struct {
// Next and previous pointers in the doubly-linked list of elements.
// To simplify the implementation, internally a list l is implemented
// as a ring, such that &l.root is both the next element of the last
// list element (l.Back()) and the previous element of the first list
// element (l.Front()).
next, prev *Element
// The list to which this element belongs.
list *List
// The value stored with this element.
Value interface{
}
}
// List represents a doubly linked list.
// The zero value for List is an empty list ready to use.
type List struct {
root Element // sentinel list element, only &root, root.prev, and root.next are used
len int // current list length excluding (this) sentinel element
}
当通过 list.New()
创建一个 list 时,会初始化一个 Element 作为 Root Pointer,它要么指向列表的初始元素,要么为 nil
。每一个 Element 除了数据字段Value
外,还有 prev
和 next
分别指向 直接前驱 和 直接后继, 来允许用户在 list 中前后移动元素。
list 容器支持的方法如下:
type Element
func (e *Element) Next() *Element
func (e *Element) Prev() *Element
type List
func New() *List
func (l *List) Back() *Element // 最后一个元素
func (l *List) Front() *Element // 第一个元素
func (l *List) Init() *List // 链表初始化
func (l *List) InsertAfter(v interface{
}, mark *Element) *Element // 在某个元素后插入
func (l *List) InsertBefore(v interface{
}, mark *Element) *Element // 在某个元素前插入
func (l *List) Len() int // 在链表长度
func (l *List) MoveAfter(e, mark *Element) // 把 e 元素移动到 mark 之后
func (l *List) MoveBefore(e, mark *Element) // 把 e 元素移动到 mark 之前
func (l *List) MoveToBack(e *Element) // 把 e 元素移动到队列最后
func (l *List) MoveToFront(e *Element) // 把 e 元素移动到队列最头部
func (l *List) PushBack(v interface{
}) *Element // 在队列最后插入元素