Arrays.asList返回的列表是否保持与原始数组集合相同的顺序?

17
我有一个ArrayList正在进行多次迭代,看起来它没有保持迭代的顺序。我深入研究了一下,发现这个迭代所用的自定义iterator标签(由别人编写)首先将传递进来的ArrayList使用Arrays.asList转换为Object[]集合再进行迭代。迭代的顺序是否丢失?这是Arrays.asList期望发生的吗?
编辑:
这里是传递给iterator标签的原始集合执行的操作:
if(collection.getClass().isArray()) {
    iterator = Arrays.asList((Object[]) collection).iterator();
} else if(collection instanceof Collection) {
    iterator = ((Collection) collection).iterator();
} else if(collection instanceof Iterator) {
    iterator = (Iterator) collection;
} else if(collection instanceof Map) {
    iterator = ((Map) collection).entrySet().iterator();
}

你的情况中是否丢失了排序? - BalusC
看起来是这样,但我正在努力找到原因,或者确定这是否是UI设计问题,而不是迭代本身的问题。我正在使用的自定义迭代器可以说是非常“棘手”。 - user4903
2
你搞混了,这个方法会检查集合是否是一个数组,如果是,就将其包装在一个列表中。如果你声称集合是 ArrayList,则只会返回迭代器,请参考 instanceof Collection 部分。 - josefx
3个回答

12
该列表仍由原始数组支持,因此项目应按照它们在数组中的顺序出现。
另外,请注意,asList是一个通用方法,因此Arrays.asList(T[])将返回一个List。
至于其他方向,List的toArray
返回一个包含此列表中所有元素的数组,按适当顺序(从第一个元素到最后一个元素)。
有两个toArray方法。 第一个返回一个Object[],第二个以数组作为其参数,并返回相同类型的数组。
这样的事情并不罕见,以下是使用String数组的示例:
String[] y = x.toArray(new String[0]);

(此示例取自List<E>JavaDoc


我添加了一些代码以更好地评估原始集合中发生的情况。 - user4903
1
@hal:数组中的元素不是有序的吗?它们不是按照索引排序的吗?你是不是把哈希映射/哈希集合/哈希表搞混了? - BalusC
@Bemrose,你提供的最后一个例子更高效的方法是:String[] y = x.toArray(new String[x.size()]); - peakit
2
@hal10001:我想你可能有些困惑......如果将一个 ArrayList 作为你所发布的代码中的 collection,那么它的 Iterator 将直接被使用,因为它是 Collection 的实例。如果提供的是一个数组,那么 Arrays.asList 将被用来将该数组桥接到一个 List 上,而不是反过来。 - ColinD
@peakit:可能吧,但我决定偷懒,从JavaDoc中借鉴示例而不是自己编写。 - Powerlord
显示剩余3条评论

3
可能迭代被打乱的地方是如果collection是一个Map。
 else if(collection instanceof Map) {
    iterator = ((Map) collection).entrySet().iterator();
}

如果collection是一个特定的HashMap,那么集合元素的顺序确实被抛弃了。
如果collection是一个TreeMap,它应该根据排序来维护集合的顺序。但是,如果你将一个由Comparable对象组成的数组转换为TreeMap,你不应该期望数组和TreeMap具有相同的顺序,因为TreeMap会对数组的内容进行排序。
此外,你也可能得到一些其他的Collection,比如HashSetPriorityQueue等,它们会改变集合的顺序。
然而,如果collection从未是一个Map,而总是一个数组,那么Arrays.asList应该保持顺序。我最好的猜测是你的问题要么在你的代码片段之外,要么出现在你传递一个数组以外的情况中。

我刚刚意识到...如果我有一个TreeMap,然后将其转换为Map,那么迭代顺序不是就丢失了吗? - user4903
@hal10001 如果它是TreeMap,迭代顺序不应该丢失(仅因为您将TreeMap视为Map并不意味着它失去了作为TreeMap的特性)。如果是这种情况,我现在有点困惑 :-p - Zach L
3
强制类型转换不会改变对象的行为或结构,它只是改变了你所引用对象的类型。 - ColinD
@hal10001 像 ColinD 说的那样。仅仅因为我把灰熊称作“熊”,并不意味着它不再是一只灰熊了。就像附近的每个人都知道的那样,它就是一只熊。 - Zach L
感谢ColinD的明确解释。 - user4903

0

您可以将 Collection 替换为 Iterable 以使其更加通用。

} else if(collection instanceof Iterable) {
    iterator = ((Iterable) collection).iterator()

注意:像 int[].class.isArray() == true 这样的原始数组是可以使用的,但它们不能被强制转换为 Object[]

我正在使用一个由别人几年前开发的JAR文件中的API,所以不幸的是我无法更改迭代器标签的实现。 - user4903

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接