我想知道,.NET中的集合实现有什么不同.
例如,我经常使用List<int>etc来存储项目列表.但是我只需要一个容器用于物品,我想我不需要所有的功能List.我只需要一个具有put方法的容器,并使客户端代码能够迭代容器.
是否有更快,更轻量级的集合实现IEnumerable<T>在.NET 中实现?
实现的最轻量级容器IEnumerable<T>是类型化数组.它没有Add方法(因此不像列表那样动态调整大小)但是如果你知道前面想要多少个元素,你可以定义数组并在给定位置插入元素.
var myArray = new int[10];
myArray[0] = 123;
myArray[1] = 234;
Run Code Online (Sandbox Code Playgroud)
如果您只需要添加和迭代,我会相信链表是最轻的。我没有看过 Stack 的实现,创建一个不占用太多空间的实现相当容易。这是一个相当幼稚的解决方案,可以针对大小进行优化。我的观点是实现轻量级集合很简单
public class Stack<T>{
readonly T _head;
readonly Stack<T> _tail;
public Stack(T head,Stack<T> tail){
_head = head;
_tail = tail;
}
public Stack<T> Push(T element){
return new Stack<T>(element,this);
}
public IEnumerator<T> GetEnumerator(){
yield return _head;
var current = _tail;
while(_tail != null){
yield return current._head;
current = current._tail;
}
}
}
Run Code Online (Sandbox Code Playgroud)
在性能方面,这将比使用预分配数组的实现慢,因为分配给元素比新建新对象要快,并且取决于内部数组的填充方式,例如。list 是这实际上可能会占用更多空间,但是可以通过每次只添加一个元素来更新一个新数组来换取性能开销,但这在性能方面具有显着的开销。您还可以选择两者之间的平衡,在大多数情况下为大量分配内存但在大多数情况下提高性能的新元素保留足够的空间。
public class Stack<T>{
T[] _heads;
T[] _tail;
int _next;
public Stack(T head,T[] tail){
_heads = new T[tail.length];
_next = _heads.Length -2;
_heads[_heads.Length -1] = head;
_tail = tail;
}
public void Push(T element){
if(_next < 0){
var length = _heads.Length;
var _new = new T[length * 2];
_heads = new T[length * 2];
_next = length * 2-1;
Array.Copy(_heads,_new,length);
Array.Copy(_tails,0,_new,length,length);
_tails = _new;
} else{
_heads[_next--] = element;
}
}
public IEnumerator<T> GetEnumerator(){
yield return _head;
var current = _tail;
while(_tail != null){
yield return current._head;
current = current._tail;
}
}
}
Run Code Online (Sandbox Code Playgroud)
并且您基本上回到了 List 等集合所具有的余额。它建立在一个内部数组上,该数组通常太大而无法在不浪费太多内存的情况下进行高速添加。
因此,与所有优化问题一样,这实际上取决于您希望针对什么进行优化。如果您愿意牺牲性能,通常可以优化内存,反之亦然