重构foreach to for循环

时间:2015-06-05 08:52:20

标签: java eclipse automated-refactoring

我在Java中有一个foreach循环(这里是简化版)

List<String> names = getNames();
for(String name:names) {
    doSomething(name);
}

是否有自动方法将其重构为传统的for循环?

我知道如何手动完成

List<String> names = getNames();
for(int i=0; i<names.size(); i++) {
    String name = names.get(i);
    doSomething(name);
}

正如您所看到的,for语句本身需要输入一些内容,并再次引入变量name并为其赋值names.get(i)。总的来说,手动编辑对我来说太容易出错了。

为什么我要这样做?我必须修复一个错误,修复是从索引1开始而不是索引0并在索引n-1结束而不是结束(遗憾的是我无法立即修复输入,我需要等待库更新如果这被认为是一个错误)。

我尝试了什么?我右键单击了for关键字并点击了“Refactor”,但就我从上下文菜单条目中可以得到的内容来说,没有任何内容可以帮我完成工作。

为什么我认为这在理论上可行?因为Resharper for Visual Studio(C#)中存在类似的功能。

仅供参考:我正在使用Eclipse Luna SR 2(4.4.2)

7 个答案:

答案 0 :(得分:10)

鼠标悬停for语句,右键单击,快速修复( Ctrl + 1 ),转换为索引循环。

应该工作!

答案 1 :(得分:7)

List<String> names = getNames();
names = names.subList(1, names.size() - 1);
for(String name : names) {
    doSomething(name);
}

当然,如果您需要多次执行此操作,可以将其置于可重用的方法中:

public static List<String> fixList(List<String> names) {
    return names.subList(1, names.size() - 1);
}

然后将其用作

List<String> names = fixList(getNames());
for(String name : names) {
    doSomething(name);
}

答案 2 :(得分:6)

在我的eclipse(Kepler RC2)中,它可以选择for关键字并使用上下文菜单中的快速修复或点击 CTRL + 1 为快捷方式。然后Eclipse为我提供了转换为索引&#39;用于&#39;环路&#34;或者&#34;转换为基于Iterator的&#39;用于&#39;环路&#34;

Screenshot of quick fix options

答案 3 :(得分:1)

您可以使用:

names = names.subList(1, names.size()-1);
for (String name : names) {
   doSomething(name);
}

或手动:

for (int i = 1; i < names.size()-1; i++) {
   String name = names.get(i);
    doSomething(name);
}

但我喜欢使用的第一个。

答案 4 :(得分:0)

小心这种重构。

原因是对于传统的链表,您的第二个for循环公式为O(N * N),因为您必须遍历链表才能评估names.get(i); 。这可能会变得昂贵。

for(String name:names) {移动时,请考虑性能影响。可能有更好的方法来修复你的直接错误,并保留当前的&#34; Big O&#34;。

for(String name : names.subList(1, names.size() - 1)) {

就是这样一种方式(Acknowledge @JB Nizet)。

答案 5 :(得分:0)

不要进行索引迭代! 这对List的所有实现都不是很好。

最好选择Iterator,如果此代码很热,让JIT优化Iterator

所以写下这个:

List<String> names = getNames();
for (String name : names.subList(1, names.size() - 1)) {
    doSomething(name);
}

或者那(少一个分配):

Iterator<String> it = getNames().iterator();
it.next(); // You seem to be sure there is more than one element in the list
while (it.hasNext()) {
    String name = it.next();
    doSomething(name);
}

答案 6 :(得分:-2)

使用java 8时,您可以使用stream api

names.stream().skip(1).reverse().skip(1).reverse().foreach(
    name -> do something(name)
);

像这样......