【问题标题】:Arraylist getting sorted when it's not supposed to?Arraylist 在不应该排序的时候得到排序?
【发布时间】:2017-07-24 13:11:10
【问题描述】:

我对这个问题感到非常沮丧。以下是正在发生的事情的要点:

import static java.lang.System.*;
import java.util.ArrayList;
public class Test {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(12);
        list.add(19);
        list.add(442);
        list.add(3);
        list.add(1);
        list.add(9);
        out.println(list.toString());
        out.println(bubbleSort(list));
        out.println(list.toString());
    }
    public static int bubbleSort(ArrayList<Integer> num) {
        int j;
        boolean flag = true;
        int temp;
        while(flag) {
            flag = false;
            for(j = 0; j < num.size() - 1; j++) {
                if(num.get(j) > num.get(j + 1)) {
                    temp = num.get(j);
                    num.set(j, num.get(j + 1));
                    num.set(j + 1, temp);
                    flag = true;
                }
            }
        }
        return num.get(0);
    }
}

输出是:

[12, 19, 442, 3, 1, 9] 1 [1, 3, 9, 12, 19, 442]

当我调用方法bubbleSort() 时,为什么ArrayList list 得到排序?当我将其称为bubbleSort(list) 而不是对超出其范围的list 本身进行排序时,该方法不应该创建list 的实例吗?我只希望bubbleSort 通过创建list 的实例、使用冒泡排序对该实例进行排序并返回该实例的第一个值来获得list 的最小值。我错过了一些非常明显的东西吗?我对这个问题的沮丧感到非常厌倦......

【问题讨论】:

  • 在 Java 中,您使用 new 关键字创建一个新实例,并且您只在您的 sn-p 中执行一次,在 main() 中。
  • @assylias:我们真的需要一个关于“什么是对象引用”的规范,它根本不会涉及整个传递过程,因为它与 95% 的问题无关人们不明白这一点。 :-)

标签: java arraylist scope


【解决方案1】:

当我将其称为bubbleSort(list) 而不是对超出其范围的list 本身进行排序时,该方法是否应该创建list 的实例?

没有。传递引用对象的值(称为对象引用)不涉及复制对象,只涉及值。

list 变量中的值是一个对象引用,它告诉 JVM 该列表对象在内存中的位置。 (我们从未看到实际值,但将它们视为像 ints 这样的数字;它们的行为与它们完全一样。)如果您将该值传递给一个方法,该方法会收到该值的副本(对象引用)——但该对象引用仍然指向同一个对象。

这和这里发生的完全一样:

List<String> list1 = new ArrayList<>();
List<String> list2 = list1;

让我们分解一下。当我们这样做时

List<String> list1 = new ArrayList<>();

new 运算符使 JVM 在内存中创建一个 ArrayList,并将对该列表的引用(JVM 理解的唯一标识符)存储在 list1 中:

list1−−−+ | +−−−−−−−−−−−−−−−+ +−−−>| (数组列表) | +−−−−−−−−−−−−−−−+ |计数:0 | |容量:16 | | ... | +−−−−−−−−−−−−−−−+

那么当我们这样做时:

List<String> list2 = list1;

那个值(上面显示为 Ref22135,但同样,我们从来没有看到它们)被复制list2

list1−−−+ | +−−−−−−−−−−−−−−−+ +−−−>| (数组列表) | | +−−−−−−−−−−−−−−−+ list2−−−+ |计数:0 | |容量:16 | | ... | +−−−−−−−−−−−−−−−+

我们现在拥有对单个对象的引用的两个副本,而不是两个对象。

出于同样的原因,将list 传递给bubbleSort 会将list 变量(Ref22135 或其他)的 复制到bubbleSort 参数中,而不是列表本身。

【讨论】:

  • 现在更有意义了,谢谢。虽然我不明白他们为什么这样做的目的,但是当我将 list 传递给 bubbleSort() 时,它会创建 内存地址 的实例,而不是 list 本身的值。跨度>
  • @parrot15:每次将对象传递给方法时都复制它会大量效率低下(而且不要忘记,根据定义,它必须是深层副本)。而复制引用是复制 4 到 8 个字节(到 JVM 寄存器或堆栈上)的问题。
【解决方案2】:

num 已经被 ref 而非 value 保存,所以你需要做的就是那个代码

import static java.lang.System.*;
import java.util.ArrayList;
public class Test {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(12);
        list.add(19);
        list.add(442);
        list.add(3);
        list.add(1);
        list.add(9);
        out.println(list.toString());
        out.println(bubbleSort(list));
        out.println(list.toString());
    }
    public static int bubbleSort(ArrayList<Integer> num) {
        //copy the array list to new array list
        ArrayList<Integer> numtemp = new ArrayList<Integer>(num);
        int j;
        boolean flag = true;
        int temp;
        while(flag) {
            flag = false;
            for(j = 0; j < numtemp.size() - 1; j++) {
                if(numtemp.get(j) > numtemp.get(j + 1)) {
                    temp = numtemp.get(j);
                    numtemp.set(j, numtemp.get(j + 1));
                    numtemp.set(j + 1, temp);
                    flag = true;
                }
            }
        }
        return numtemp.get(0);
    }
}

【讨论】:

  • 正是我需要的,谢谢。我的 Comp sci 课程从未教过我关于通过引用传递和通过值传递的知识……我想我还有一些阅读要做。
  • @parrot15:要明确一点:这不是传递引用。 “传递引用”是一个艺术术语,指的是传递对变量的引用,因此被调用的方法可以到达并更改变量中的值。 Java 从不这样做。 Java 确实有对象引用,但它们和其他所有东西一样都是按值传递的。
猜你喜欢
  • 1970-01-01
  • 2019-09-16
  • 1970-01-01
  • 2011-07-20
  • 2012-10-24
  • 2011-07-15
  • 2014-06-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多