提问人:Zephyr 提问时间:5/31/2023 更新时间:5/31/2023 访问量:28
为什么在 Java 子方法中对 Map.Entry<Integer,Integer> 的更新在作为状态传递时不反映在父方法中?[复制]
Why don't updates to Map.Entry<Integer,Integer> in a Java child method reflect in the parent method, when passed around as state? [duplicate]
问:
我正在尝试解决一个简单的 leetcode 问题。这个问题是一个树问题,要求我们归还最深的叶子总和。https://leetcode.com/problems/deepest-leaves-sum/description/
我使用DFS来解决这个问题。我将一个 level 变量作为递归 DFS 调用的输入之一传递。我在叶节点(基本情况)报告结果(如果级别确实比我们之前看到的更深)。我使用 Map.Entry<Integer, Integer> 来保存结果 - 它将最深的级别映射到其各自的总和。
我注意到的是,当我将此 Map.Entry<> 声明为全局类级变量时,这些方法正确地反映了对它所做的更新。但是当我在父函数中将其初始化为 null 并在 dfs 调用中将其作为状态传递时,尝试在叶节点上更新它 - 更改不会反映在 main 方法中。
我很难理解为什么?
这行得通
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
Map.Entry<Integer, Integer> deepestLevelSum;
public int deepestLeavesSum(TreeNode root) {
if (root.left == null && root.right == null)
return root.val;
deepestLevelSum = null;
dfsHelper(root, 0);
return deepestLevelSum.getValue();
}
private void dfsHelper(TreeNode root, int level){
//report result if valid
if (root.left == null && root.right == null) {
if (deepestLevelSum == null || deepestLevelSum.getKey() < level) {
deepestLevelSum = new HashMap.SimpleEntry(level, root.val);
} else if (deepestLevelSum.getKey() == level){
deepestLevelSum.setValue(deepestLevelSum.getValue()+root.val);
}
} else {
if (root.left != null)
dfsHelper(root.left, level+1);
if (root.right != null)
dfsHelper(root.right, level+1);
}
}
}
但事实并非如此。在 dfs 调用中对 Map.Entry<Integer、Integer> deepestLevelSum 变量所做的更改不会反映在 main(父)方法中。
class Solution {
public int deepestLeavesSum(TreeNode root) {
if (root.left == null && root.right == null)
return root.val;
Map.Entry<Integer, Integer> deepestLevelSum = new HashMap.SimpleEntry(0, root.val);
dfsHelper(root, 0, deepestLevelSum);
return deepestLevelSum.getValue();
}
private void dfsHelper(TreeNode root, int level, Map.Entry<Integer, Integer> deepestLevelSum){
//report result if valid
if (root.left == null && root.right == null) {
if (deepestLevelSum == null || deepestLevelSum.getKey() < level) {
deepestLevelSum = new HashMap.SimpleEntry(level, root.val);
} else if (deepestLevelSum.getKey() == level){
deepestLevelSum.setValue(deepestLevelSum.getValue()+root.val);
}
} else {
if (root.left != null)
dfsHelper(root.left, level+1, deepestLevelSum);
if (root.right != null)
dfsHelper(root.right, level+1, deepestLevelSum);
}
}
}
据我了解,该条目是可变的 - 这就是为什么我们有 setValue() 方法,但我在对按引用传递的基本理解中是否遗漏了一些东西?
答:
在 Java 中,当您将对象作为参数传递给方法时,您实际上是在将引用的副本传递给该对象。
因此,当您将 deepestLevelSum 重新分配为
deepestLevelSum = new HashMap.SimpleEntry(level, root.val);
您正在为方法内的局部 deepestLevelSum 变量分配一个新引用,但它不会影响方法外部的原始引用
return deepestLevelSum.getValue();
不返回预期的值。
最后,你所做的是“覆盖”你拥有的引用副本,而你所期望的是“覆盖”引用指向的对象。
希望这是清楚的
评论