JAVA:为什么我需要在这个函数中创建一个新的列表对象?

时间:2017-02-15 20:54:40

标签: java parameter-passing

修改

该函数是lintcode问题“组合和”答案的一部分,如果我使用第二个版本,则输出为“[[],...,[]],其中所有内部列表为空,即使它们传递给了值。当我只是切换到第一个版本而不改变任何其他东西时,它会起作用。

所以我认为它与Java参数传递过程有关,我不明白。你能解释一下为什么只有第一个版本可以工作吗?

代码:

private void helper(ArrayList<ArrayList<Integer>> result, ArrayList<Integer> list, int target, ...) {
    if (target == 0) {
        result.add(new ArrayList<Integer>(list));

        return;
    }

    ...
}

问题:

为什么我需要创建一个新的 ArrayList 对象,然后将其添加到结果

此方法与下面的代码有什么区别:

private void helper(ArrayList<ArrayList<Integer>> result, ArrayList<Integer> list, int target, ...) {
    if (target == 0) {
        result.add(list);

        return;
    }

    ...
}

有人可以向我解释一下吗?谢谢!

5 个答案:

答案 0 :(得分:2)

通过将现有列表传递给构造函数来创建新的ArrayList对象时,列表中包含的整数将复制到该新列表。

如果仅将列表添加到结果中,并且之后通过例如修改列表进行修改。根据上下文,添加或删除元素,修改会反映在结果中,这些结果可能是也可能不是。

运行此代码时差异变得明显:

sudo vi /etc/sysconfig/selinux

这里,前两个列表被添加到每个包含一个Integer的结果中。使用helper1添加第一个列表,使用helper2添加第二个列表。之后,通过添加另一个Integer来修改两个列表。对于list1,更改对我们的结果没有任何影响,但list2的修改确实如此。

答案 1 :(得分:0)

最终,他们正在做同样的事情,但是,我能注意到的唯一区别是第一个使用更多内存,并且不需要实际构建已存在的新ArrayList。

答案 2 :(得分:0)

在第一个示例中,您实际上并未使用给定值,而是创建一个新的本地List。 在第二个示例中,您是否使用给定值。

例如,如果您调用该方法并将其作为ArrayList<Integer>list [2,5,52,888]的值,则将该值添加到现有列表中。

答案 3 :(得分:0)

在第二个示例中,如果在方法之外更改列表,则结果中的列表也会更改,因为它是列表的相同实例。

在第一个示例中,您将创建一个列表副本,将其与修改隔离开来。

答案 4 :(得分:0)

@CollinD提出了一个很好的问题,以确保你知道帮助方法的真正意图。

当您使用Java传入对象时,您将传入对象的引用。对引用的任何更改都将反映在您创建的原始对象中。

 public static void main(String[] args) {
    ArrayList<ArrayList<Integer>> arrays = new ArrayList<>();
    ArrayList<Integer> list1 = new ArrayList<>();
    list1.add(1);
    list1.add(2);
    helper(arrays, list1);
    arrays.get(0).add(3);

    list1.forEach(e -> System.out.print(e));
    System.out.print("\n");
    arrays.get(0).forEach(e-> System.out.print(e));

}

尝试使用两种不同的辅助方法执行此示例代码。

您会注意到原始方法将为您提供两个不同的值列表。

12
123

虽然第二种方法为您提供相同的值

123
123

这是因为ArrayList(list)的构造函数将list中的值复制到新对象。第二种方法简单地将引用列表添加到稍后要使用的数组中,在我给出的示例项目中,您现在有两种不同的方式来访问list1。