Delphi
中最基本的列表是TList
类和TList<T>
泛型类,还有线程安全的TThreadList
类和TThreadList<T>
泛型类,底层实现是数组。Go
用的是container/list
包,内部实现是双向链表。
Delphi
TList
TList
里存的是指针,使用时注意处理好指针即可。
//声明
var l: TList;
//构造
l := TList.Create;
//添加
l.Add(p);
//元素个数
n := l.Count;
//列表容量
cap := l.Capacity;
//取值
p1 := l.Items[0];
p2 := l.Extract(p1); //找到指针p1并从列表中取出,列表中将不再有p1,若其后还有元素,则前移填充空缺。
p := l.First; //取第一个元素
p := l.Last; //取最后一个元素
//查找元素的索引
i := l.IndexOf(p);
//修改
l.Items[0] := p2;
//删除
l.Delete(0);
l.Remove(p2);
//清空
l.Clear; //只清空了内部的指针数组,并没有释放指针指向的内存
//释放
l.Free;
引用System.Contnrs
单元后可以使用TObjectList
类和TComponentList
类,操作方法与TList
相同,只是删除元素或清空列表后可自动释放元素。
TThreadList
TThreadList
是加了锁的TList
,所以多线程操作时是线程安全的。
//声明
var tl: TThreadList;
//构造
tl := TThreadList.Create;
//添加
tl.Add(p);
//删除
tl.Remove(p);
//加锁
l := tl.LockList; //返回TList,方便更精细的操作
//解锁
tl.UnlockList;
//清空
tl.Clear; //同TList,只清空了内部的指针数组,并没有释放指针指向的内存
//释放
tl.Free;
TList<T>
需要引用System.Generics.Collections
单元,使用方法与TList
类似。
//操作元素以记录为例
TR = record
i: Integer;
s: string;
end;
//声明
var rl: TList<TR>;
//构造
rl := TList<TR>.Create;
//添加
rl.Add(R1); //返回添加的位置
rl.Insert(1, R2); //在指定位置插入
//删除
rl.Remove(R1); //按元素删除
rl.Delete(0); //按索引删除一个元素
rl.DeleteRange(0, n); //按索引删除连续多个元素
R := rl.Extract(R2); //提取元素
R := rl.ExtractAt(0); //按索引提取元素
//清空
rl.Clear; //会自动释放元素所占内存
//释放
rl.Free;
TThreadList<T>
TThreadList<T>
是加了锁的TList<T>
,多线程操作时是线程安全的。
//声明
var rtl: TThreadList<TR>;
//构造
rtl := TThreadList<TR>.Create;
//添加
rtl.Add(R);
//删除
rtl.Remove(R);
//加锁
rl := rtl.LockList; //返回TList<TR>,方便更精细的操作
//解锁
rtl.UnlockList;
//清空
rtl.Clear;
//释放
rtl.Free;
Go
//声明
var l list.List //l是List结构体
l := list.New() //l是指向List结构体的指针
//添加
e1 := l.PushFront(123) //在头部添加元素
e2 := l.PushBack("abc") //在尾部添加元素
e3 := l.InsertAfter("xyz", e1) //在指定元素后添加新元素
e4 := l.InsertBefore(456, e2) //在指定元素前添加新元素
//取值
e5 := l.Front() //返回第一个元素
e6 := l.Back() //返回最后一个元素
//从头顺序遍历
for i := e5; i != nil; i = i.Next() {
fmt.Println(i.Value)
}
//从尾逆序遍历
for i := e6; i != nil; i = i.Prev() {
fmt.Println(i.Value)
}
//移动元素
l.MoveToFront(e3) //把e3移动到头部
l.MoveToBack(e4) //把e4移动到尾部
l.MoveAfter(e1, e3) //把e1移动到e3后面
l.MoveBefore(e2, e1) //把e2移动到e1前面
//删除
l.Remove(e3)
//元素个数
n := l.Len()
//清空
l.Init()
由于Go
语言语法糖的原因,指针与指针指向的对象的使用方法完全一致。