Iterablecollectionsthatcanbemutatedduringiterations列表和外发项目列表。传入列表被迭代,一些被复制到新列表。在迭代过程中,可能会向新列表中添加一些新元素。迭代后,旧的传入列表被新的传出列表替换。整个过程本身就是一个循环。因此,与具有这些添加/删除属性的元素相比,每次将元素复制到新构造的集合对象似乎效率低下。我正在考虑某种队列,让我可以预览当前项目,然后将其出列或不出列,然后继续进行下一个项目。我可以将更多项目添加到队列的头部,但它们不会被看到,因为我正在接近尾声。双向链表可能具有这些属性,对吗?如果您真的想知道它的用途,我的回答中还有第二个大代码块。在C#中,使用List和for(...)而不是foreach(...)很容易:usingSystem;使用System.Collections.Generic;使用System.Linq;namespaceDemo{staticclassProgram{staticvoidMain(){Listlist=Enumerable.Range(1,10).ToList();for(inti=0;i这里的关键是使用index而不是foreach,并且在currentindex(不需要读你的需求)之前。但是,如果你真的需要在当前index之前添加或删除元素,这不起作用(或者至少,它变得更复杂)。对于C#,您可以像在良好的C中那样使用LinkedList,如下所示:publicDoStuff(LinkedListlist){varnode=list.First;while(node!=null){//dostuffwithnodenode=node.Next;}}节点是LinkedListNode类型,你可以使用node.Value访问值,使用list.Remove(node)删除。对于Telem,您还有list.AddAfter(node,elem)、list.AddBefore(node,elem)、list.AddFirst(elem)和list.AddLast(elem)。所有这些操作都是O(1)。您可以将此方法用于各种迭代,如果您只想迭代原始元素,请在执行任何操作之前缓存下一个节点并记住最后一个节点:varlastNode=list.Last;varnode=list.First;while(node!=lastNode.Next){varnextNode=node.Next;//用节点做事node=nextNode;}Java中的等效数据结构也称为LinkedList。但是,标准ListIterator上的ListIteratorList可能更清晰。在java中,有CopyOnWriteArrayList可以执行您想要的操作:每次更改任何内容时,它都会复制支持数组。但这确实意味着一旦开始迭代,任何迭代都是“不可变的”,因此您可以随意删除/添加到底层集合,而不会影响任何正在运行的迭代器。您还可以构建自己的具有此行为的集合类型。这是一个三级循环:publicclassConstantIterationArrayListextendsArrayList{publicIteratoriterator(){returnnewArrayList(this).iterator();}}(上面创建了列表的副本,然后为您提供了副本的迭代器,因此可以方便地确保对列表的任何修改都不会对迭代器产生任何影响)。这是您问题的真正问题:上面的内容会不时制作底层数据存储的副本(CopyOnWriteArrayList上方的代码段每次都是迭代器。CopyOnWriteArrayList每次调用remove()或add()时)。“复制底层数据存储”操作需要O(n)时间,因为对于两倍大的列表,它需要两倍的时间。ArrayLists通常具有remove()操作的属性,除非您要删除列表末尾或非常接近列表末尾的元素,否则执行O(n)操作:从列表中删除元素需要两倍的时间,如果列表是两倍大。幸运的是,现代CPU具有相当大的缓存,并且可以以极快的速度在缓存页面内运行。这转化为:虽然复制数据感觉效率低下,但实际上它比基于LinkedList语义的数据存储快得多,只要支持数组适合页面左右。我们正在谈论多达1000个元素的给予或接受。(请注意,通常情况下,您使用LinkedList所做的几乎所有事情都是O(n),虽然ArrayList在现代CPU架构上往往做得很好,但LinkedList往往做得很差。关键是:LinkedList很少是正确答案!)因此,如果此列表中的项目不超过1000个,我会继续使用CopyOnWriteArrayList或我在上面为您编写的自定义类。但是,如果您有多个ArrayList则不是此处使用的正确数据存储。即使您现在忘记了不断迭代的需要;在大型数组列表上调用remove()是一个坏主意(除非非常接近列表的末尾)。在这种情况下,我会准确描述您需要使用该数据类型做什么,以及您需要快速做什么,一旦您有了完整的列表,请尝试找到一个完全符合您需要的集合类型,并在(可能)如果不存在完美匹配的特定对象,请自己制作一个。如上所述,当您必须滚动自己的数据类型时,通常最好让现有数据类型完成大部分工作,因此要么扩展现有数据类型,要么包装一个。以上就是C#学习教程:一个可迭代的集合,在迭代过程中可以变异并共享所有的内容。如果对大家有用,需要进一步了解C#学习教程,希望大家多多关注。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
