2015-02-24 34 views
7

我找不到任何关于此的主题。我想知道这是否是安全的像一个波纹管的循环过程中更改列表类的引用:在Java循环期间更改了列表对象引用

Tree minimalTree = someTree; 
for (Tree st : minimalTree.getSubtrees()) { 
    if (condition) 
    minimalTree = st; 
} 

是否迭代被复位,为新的参考重新开始?

编辑:我忘了说:这段代码适用于我想要缩小树中元素搜索范围的情况,比方说,包含某些元素的较小的树。在这种情况下,继续只查看“minimalTree”的内部结构而不是整个“someTree”结构会更快。

+1

会发生什么事,当你测试它? – 2015-02-24 21:04:03

+0

您应该为此使用递归调用。 – biziclop 2015-02-24 21:16:05

+0

直到现在它似乎仍能正常工作,但我不确定它是否可以用于大规模处理。但也许@biziclop是正确的,应避免这种编码... – 2015-02-24 21:19:27

回答

6

不,重复不会被重置。按照JLS

增强的for语句等价于一个基本为 声明形式:

for (I #i = Expression.iterator(); #i.hasNext();) { 
    {VariableModifier} TargetType Identifier = (TargetType) #i.next(); 
    Statement 
} 

的定义,使其明显迭代器只初始化一次,前循环的第一次迭代。

使用增强for语句遍历数组时的行为在这方面是类似的。

但是我个人认为它很糟糕的做法,因为它使代码很难理解。

2

实际上,有两个问题:

我想知道这是否是安全的像一个波纹管的循环过程中更改列表类的引用:

是的,是安全的。为了安全,我的意思是:改变参考不会干扰已经运行的循环。

迭代器是否重置并重新启动新引用?

不,迭代器不会重置。这完全与安全相反。

在我看来,改变循环内的迭代器或集合变量并不是一个好习惯。它使代码更难理解,并且可能结果不是你期望的结果(就像你的情况,我理解你期望循环开始重新评估集合)。

在你的情况,在封装的方法和递归调用它的子树:

Tree findMinimalTree(Tree tree) { 
    for (Tree st : tree.getSubtrees()) { 
    if (condition) 
     return findMinimalTree(st); 
    } 
    return tree; 
} 
+0

我不同意。阅读biziclop的答案。用我的话来说,minimalTree.getSubtrees()[。iterator()]在进入循环时被精确计算一次。之后,你可以让minimalTree指向任何你想要的。记住assigment minimalTree = st不会改变之前由minimalTree引用的对象(这里C++会做的事情)。它只是改变参考minimalTree,我。即minimalTree指向的对象。 – fjf2002 2015-02-24 21:40:25

+0

是的,我了解你的观点。在我看来,问题是(i)乍一看似乎像C++对应物一样工作,并且(ii)当您调试时,您无法看到您正在迭代的集合。 – 2015-02-24 21:50:53

+0

“这似乎工作”不是表达这一点的适当方式,我会尽力改善它。有什么建议么? – 2015-02-24 21:54:09