对于值类型,通用集合的性能优于非泛型集合。 (即List vs. ArrayList)。
但除了拳击拆箱步骤之外,为什么呢?一旦添加到集合中,值类型对象存储在哪里?在非泛型集合中,它们将被装箱并存储在堆上,在泛型中有什么不同?
答案 0 :(得分:12)
在泛型中,例如List<T>
,它们仍然存储在堆上。不同之处在于,在内部,List<int>
生成一个整数数组,并且可以直接存储数字。使用ArrayList,您最终会存储一个对盒装整数值的引用数组。
答案 1 :(得分:8)
相关的实现细节是List<T>
的底层存储是T []。因此,对于List<int>
,值将存储在int []中。整数存储在一个连续的内存块中,从垃圾收集堆中分配。
使它如此快速的原因不仅仅是整数没有盒装,而是int []在CPU缓存中运行得非常好。当您读取第一个元素时,您基本上可以免费获得下一个15,而无需读取慢速RAM或二级缓存。这对于盒装int来说效果不是很好,因为它太大而且额外的引用可能具有较差的缓存局部性。但是,垃圾收集器真的有助于通过压缩堆来消除成本。
答案 2 :(得分:1)
ArrayList是对存储在堆中的对象的引用的本地数组。
引用类型的通用列表是对存储在堆中的对象的本地引用数组。
值类型的通用列表是这些值类型的本地数组。
内存有两个区域,大多数引用称为“堆栈”和“堆”。大多数使用这些术语的人都不知道为什么。 (“堆栈”可能是堆栈,但堆几乎肯定不是堆)。我更喜欢“Over Here”和“Over There”这两个词。装箱时,值类型数据存储在“Over There”。当存储在数组中时(可能在通用List中),值类型数据存储在“Over Here”中。 “在这里”更好。
答案 3 :(得分:0)
除了装箱和拆箱之外,还有几个原因,包括内存缓存以及枚举它们执行作业的方式。查看this post, especially the comments。
答案 4 :(得分:0)
泛型中的性能提升通常仅与泛型使用的值类型相比,存储在非泛型等价物中的值类型。
这是因为使用泛型值类型不需要转换为对象并存储在堆上(装箱)。实际上,它们可以保留在更高性能的堆栈上。