当前位置:  开发笔记 > 编程语言 > 正文

如何将List <T>初始化为给定大小(而不是容量)?

如何解决《如何将List<T>初始化为给定大小(而不是容量)?》经验,为你挑选了6个好方法。

.NET提供了一个通用列表容器,其性能几乎相同(请参阅阵列性能与列表问题).但是它们在初始化方面完全不同.

使用默认值很容易初始化数组,根据定义,它们已经具有一定的大小:

string[] Ar = new string[10];

这允许人们安全地分配随机项目,比如说:

Ar[5]="hello";

列表事情更棘手.我可以看到两种方法进行相同的初始化,这两种方式都不是你所谓的优雅:

List L = new List(10);
for (int i=0;i<10;i++) L.Add(null);

要么

string[] Ar = new string[10];
List L = new List(Ar);

什么是更干净的方式?

编辑:到目前为止的答案是指容量,这不是预先填充列表.例如,在刚创建的容量为10的列表中,无法做到L[2]="somevalue"

编辑2:人们想知道为什么我想以这种方式使用列表,因为它不是他们打算使用的方式.我可以看到两个原因:

    人们可以非常有说服力地认为列表是"下一代"阵列,增加灵活性几乎不会受到惩罚.因此,默认情况下应该使用它们.我指出它们可能不那么容易初始化.

    我目前正在编写的是一个基类,它提供默认功能作为更大框架的一部分.在我提供的默认功能中,List的大小在高级中是已知的,因此我可以使用数组.但是,我想为任何基类提供动态扩展它的机会,因此我选择了一个列表.

小智.. 115

List L = new List ( new string[10] );

+1:刚刚遇到一个情况,我需要一个可变大小的列表,在通过索引填充之前用一组固定的空值进行初始化(然后添加额外的数据,因此数组不合适).这个答案得到了实际和简单的投票. (4认同)

我个人认为这是最干净的方式 - 虽然在问题机构中提到它可能是笨拙的 - 不知道为什么 (3认同)

@RBT这是此方法的唯一缺点:*不会*重复使用该数组,因此您将立即拥有该数组的两个副本(如您所知,List在内部使用数组)。在极少数情况下,如果元素数量过多或存在内存限制,则可能会出现问题。是的,一旦List构造函数完成,多余的数组将有资格进行垃圾回收(否则将造成严重的内存泄漏)。请注意,符合条件并不意味着“立即收集”,而是下次运行垃圾收集时。 (2认同)

此答案分配10个新字符串-然后遍历它们,并根据需要将其复制。如果您正在使用大型阵列;那么甚至不要考虑这一点,因为它需要的内存是接受的答案的两倍。 (2认同)


Jon Skeet.. 72

我不能说我经常需要这个 - 你能否详细说明你为什么要这样做?我可能会把它作为一个静态方法放在一个帮助器类中:

public static class Lists
{
    public static List RepeatedDefault(int count)
    {
        return Repeated(default(T), count);
    }

    public static List Repeated(T value, int count)
    {
        List ret = new List(count);
        ret.AddRange(Enumerable.Repeat(value, count));
        return ret;
    }
}

可以使用,Enumerable.Repeat(default(T), count).ToList()但由于缓冲区大小调整,这将是低效的.

编辑:如评论中所述,如果您愿意,可以T使用循环填充列表.那也会稍快一些.就个人而言,我发现代码使用count更具描述性,并怀疑在现实世界中性能差异是无关紧要的,但您的里程可能会有所不同.



1> 小智..:
List L = new List ( new string[10] );


+1:刚刚遇到一个情况,我需要一个可变大小的列表,在通过索引填充之前用一组固定的空值进行初始化(然后添加额外的数据,因此数组不合适).这个答案得到了实际和简单的投票.
我个人认为这是最干净的方式 - 虽然在问题机构中提到它可能是笨拙的 - 不知道为什么
@RBT这是此方法的唯一缺点:*不会*重复使用该数组,因此您将立即拥有该数组的两个副本(如您所知,List在内部使用数组)。在极少数情况下,如果元素数量过多或存在内存限制,则可能会出现问题。是的,一旦List构造函数完成,多余的数组将有资格进行垃圾回收(否则将造成严重的内存泄漏)。请注意,符合条件并不意味着“立即收集”,而是下次运行垃圾收集时。
此答案分配10个新字符串-然后遍历它们,并根据需要将其复制。如果您正在使用大型阵列;那么甚至不要考虑这一点,因为它需要的内存是接受的答案的两倍。

2> Jon Skeet..:

我不能说我经常需要这个 - 你能否详细说明你为什么要这样做?我可能会把它作为一个静态方法放在一个帮助器类中:

public static class Lists
{
    public static List RepeatedDefault(int count)
    {
        return Repeated(default(T), count);
    }

    public static List Repeated(T value, int count)
    {
        List ret = new List(count);
        ret.AddRange(Enumerable.Repeat(value, count));
        return ret;
    }
}

可以使用,Enumerable.Repeat(default(T), count).ToList()但由于缓冲区大小调整,这将是低效的.

编辑:如评论中所述,如果您愿意,可以T使用循环填充列表.那也会稍快一些.就个人而言,我发现代码使用count更具描述性,并怀疑在现实世界中性能差异是无关紧要的,但您的里程可能会有所不同.



3> Ed S...:

使用以int("capacity")作为参数的构造函数:

List = new List(10);

编辑:我应该补充一点,我同意弗雷德里克.您使用List的方式与首先使用它的整个推理背道而驰.

EDIT2:

编辑2:我目前正在编写的是一个基类,它提供默认功能作为更大框架的一部分.在我提供的默认功能中,List的大小在高级中是已知的,因此我可以使用数组.但是,我想为任何基类提供动态扩展它的机会,因此我选择了一个列表.

为什么有人需要知道具有所有空值的List的大小?如果列表中没有实际值,我希望长度为0.无论如何,这是cludgy的事实表明它违背了类的预期用途.


这个答案没有在列表中分配10个空条目(这是要求),它只是在需要调整列表大小*(即容量)之前为10个条目*分配空间,所以这与`new List <没什么不同string>()`就问题而言.尽管获得了如此多的票数,但做得很好:)
@Bitterblue:此外,任何类型的预分配映射,您可能没有预先拥有所有值.肯定有用处; 我在经验不足的日子里写了这个答案.
重载的构造函数是“初始容量”值,而不是“大小”或“长度”,并且它也不初始化项目

4> Frederik Ghe..:

如果要使用固定值初始化它,为什么使用List?我可以理解 - 为了性能 - 你想给它一个初始容量,但它不是一个列表比常规数组的优点之一,它可以在需要时增长?

当你这样做:

List = new List(100);

您创建一个容量为100整数的列表.这意味着在添加第101个项目之前,您的列表不需要"增长".列表的基础数组将初始化为100.


他要求列出一个列表,其中每个元素都已初始化,列表的大小不仅仅是容量.这个答案现在不正确.

5> mini998..:

首先创建一个数组,其中包含所需的项目数,然后将其转换为列表。

int[] fakeArray = new int[10];

List list = fakeArray.ToList();



6> Welbog..:

初始化列表的内容不是真正的列表.列表旨在容纳对象.如果要将特定数字映射到特定对象,请考虑使用键值对结构,如散列表或字典而不是列表.

推荐阅读
喜生-Da
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有