在“列表的列表”中添加列表会通过引用添加吗?

huangapple go评论91阅读模式
英文:

Is adding list in List of Lists added by reference?

问题

我试图理解Java对象引用。到目前为止我学到的是:

  1. 对象的引用是按值传递的,因此在该对象中添加的内容在方法返回后仍然可用。
  2. 在一个方法中创建一个新的对象 foo,该方法接收对象 foo 作为参数,将不会反映在本地创建的 foo 对象上对传递的 foo 对象所做的更改。

基于这个知识,我试图理解为什么以下代码片段没有从当前列表中移除已添加到结果列表的对象。

尽管下面的代码将 currentList 的引用添加到 resultList 中,而且我们正在从 currentList 中移除元素,但在递归结束时列表并没有为空。

findCombations(condidates, 0, target, new ArrayList<Integer>(), result);

public void findCombinations(int[] candidates, int index, Int target, List<Integer> currentList, List<List<Integer>> result) {
    if(target == 0) {
        result.add(currentList);
        return;
    }
    if(target < 0) {
        return;
    }

    for(int i = index; i < candidates.length; i++) {
        if(i == index && candidates[i] != candidates[i - 1]) {
            currentList.add(candidates[i]);
            findCombinations(candidates, i + 1, target - candidates[i], currentList, result);
            currentList.remove(currentList.size() - 1); //为什么从这个列表中移除数字不会移除已添加到结果列表的 currentList 中的数字?
        }
    }
}

可以有人帮助我理解这种行为吗?

编辑:

这是一个LeetCode问题,需要找到导致目标的唯一组合:

我们必须找到所有导致给定目标的唯一数字组合。我们不能有重复的集合/组合。提供的代码在给定数组上进行DFS,根据在数组中遇到的元素进行组合。有两个基本情况,当目标==0时,我们只需将 currentList 添加到 resultList 中。currentList 包含使和等于目标的数字,另一个基本情况是如果 target < 0,这种情况下,我们结束递归。

输入:candidates = [10,1,2,7,6,1,5],target = 8,
解集如下:

[
  [1, 7],
  [1, 2, 5],
  [2, 6],
  [1, 1, 6]
]
英文:

I'm trying to understand java object references. What I learned so far is

  1. Objects' references are passed by value, so adding something in that object will be available in the object after the method returns.
  2. Creating a new object foo inside a method that received the object foo as argument will not reflect changes made on locally created foo object, on passed foo object.

Based on this knowledge, I'm trying to understand why the following code snippet isn't removing objects from current list that've been added to result list.

The code below doesn't suffer from empty list at the end of recursion even though it's adding references of currentList to resultList & we're removing elements from currentList.

findCombations(condidates, 0, target, new ArrayList&lt;Integer&gt;(), result); 
public void findCombinations(int[] candidates, int index, Int target, List&lt;Integer&gt; currentList, List&lt;List&lt;Integer&#187; result) { 
	if(target == 0) { 
		result.add(currentList); 
		return; 
	} 
	if(target &lt; 0) { return; } 
	
	for(int i = index; i &lt; candidates.length; i++) {
	 if(i == index &amp;&amp; candidates[i] != candidates[i - 1]) { 
		 currentList.add(candidates[i]); 
		 findCombinations(candidates, i + 1, target - candidates[i], currentList, result); 
		 currentList.remove(currentList.size() - 1); //why removing numbers from this list not removing the numbers from the currentList that&#39;s been added to result list?
	 }
 }

Can someone please help me understand this behavior?

EDIT:

This is a leetcode question that requires unique combinations that lead to target:
We've to find all the unique number combinations whose sum lead to the given target. We can't have duplicate sets/combinations.
The provided code is doing DFS on the given array & finding the combinations based on subtracting an element that it comes across in the array. There are 2 base cases, when the target == 0, we just add the currentList in resultList. CurrentList contains the numbers whose sum == target & the other base case is if target < 0, in that case, we end recursion.

Input: candidates = [10,1,2,7,6,1,5], target = 8,
A solution set is:
[
  [1, 7],
  [1, 2, 5],
  [2, 6],
  [1, 1, 6]
]

答案1

得分: 0

是的,是这样的。方法调用result.add(currentList)会将对currentList的引用添加到result列表中。在此之后,您对currentList所做的任何更改也将通过"result"可见,因为它持有对同一对象的引用。

简化示例:直观地说,您可能认为这个程序应该打印出[[“hello”],[]],但实际上它打印出[[], []],因为result对同一列表实例持有两个引用。

List<List<String>> result = new ArrayList<>();
List<String> currentList = new ArrayList<>();

currentList.add("hello");
result.add(currentList);

currentList.remove(0);
result.add(currentList);

System.out.println(result);

如果您想阻止这种情况发生,可以在将其添加到result时创建currentList的副本。

// 添加一个副本,而不是对同一列表的引用
result.add(new ArrayList<>(currentList));
英文:

> Is adding list in List of Lists added by reference?

Yes, it is. The method call result.add(currentList) adds a reference to currentList to the result list. Any changes that you make to currentList after this point will be seen also through "result," because it holds a reference to the same object.

Simplified example: intuitively you might think this program should print [[&quot;hello&quot;], []] but instead it prints [[], []] because result holds two references to the same instance of list.

List&lt;List&lt;String&gt;&gt; result = new ArrayList&lt;&gt;();
List&lt;String&gt; currentList = new ArrayList&lt;&gt;();

currentList.add(&quot;hello&quot;);
result.add(currentList);

currentList.remove(0);
result.add(currentList);

System.out.println(result);

If you want to stop this from happening, you can create a copy of currentList when you add it to result.

// add a copy instead of a reference to the same list
result.add(new ArrayList&lt;&gt;(currentList));

huangapple
  • 本文由 发表于 2020年8月23日 20:21:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/63546884.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定