为什么不使用 Arrays.asList 创建的列表对值进行拆箱?

Why don't lists created with Arrays.asList unbox the values?

我一直在用Arrays.asList做一个二维的ArrayList如下:

ArrayList<List<Integer>> li = new ArrayList<List<Integer>>();
for(int i = 0; i < 100; i++){
    li.add(Arrays.asList(1, (int)(Math.random() * 100)));
}

当我尝试按如下方式对元素进行排序时:

Collections.sort(li, new Comparator<List<Integer>>(){
    public int compare(List<Integer> l1, List<Integer> l2){
        if(l1.get(0) == l2.get(0)){
            return l1.get(1) - l2.get(1);
        }
        return l1.get(0) - l2.get(0);
    }
});

元素未按第二个索引正确排序。

然而,当我不使用 Arrays.asList,而是这样创建新的 ArrayList 时:

ArrayList<List<Integer>> li = new ArrayList<List<Integer>>();
for(int i = 0; i < 100; i++){
    ArrayList<Integer> toAdd = new ArrayList<Integer>();
    toAdd.add(1); 
    toAdd.add((int)(Math.random() * 100));
    li.add(toAdd);
}

然后排序工作。

我知道 Arrays.asList 不会复制值,而是 "backed" 原始数组。但是,比较函数中的 get(0) 调用不应该自动拆箱值吗?

我能发现的唯一问题是以下 if 语句:

if(l1.get(0) == l2.get(0)) {
}

它比较所有列表的第一个索引,在给定的代码中总是1。当您使用 == 运算符时,您实际上是在比较 对象引用 。不是它们的值是否相等,而是两个不同的变量是否指向内存中完全相同的对象。

只要你比较-128和127之间的整数就可以了。这个范围内的值是缓存的,因此两个不同的Integer类型的变量可以参考到同一个对象。

Integer a = 127;
Integer b = 127;
System.out.println(a == b); // prints true

Integer c = 128;
Integer d = 128;
System.out.println(c == d); // prints false

但是因为您的代码保持在缓存整数的范围内,所以它应该可以正常工作。

如果您使用 ==Object 进行比较,则您只比较参考文献。在这种情况下不需要使用自动拆箱。此外 Java 有时可以通过只创建一次来节省堆来优化创建相同的对象,因此通过引用进行比较有时有效,有时无效。