Foreach refactoring for a loop

I have a foreach loop in Java (simplified version here)

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

Is there an automated way to refactor this into a traditional for loop?

I know how to do it manually

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

As you can see, in the for statement you need to enter a little text, and also enter the name variable and assign it the value names.get(i) . In general, manual editing is too error prone for me.

Why do I want to do this? I have to fix the error, and the correction should start from index 1 instead of index 0 and end with index n-1 instead of the end (unfortunately, I can’t fix the input right away, I need to wait for the library to update if it is recognized as an error).

What have i tried? I right-clicked the for keyword and clicked on "Refactor", but as far as I can get from the context menu entries, nothing would work for me.

Why do I think this could theoretically work? Since similar functionality exists in Resharper for Visual Studio (C #).

FYI: I am using Eclipse Luna SR 2 (4.4.2)

+6
source share
7 answers

Hover over for , right-click, Quick Fix ( Ctrl + 1 ), convert to indexed loop.

Must work!

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

Of course, you can apply this to a reusable method if you need to do this several times:

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

and then use it like

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

In my eclipse (Kepler RC2), it works to select the for keyword and either use the quick fix in the context menu or press CTRL + 1 for the shortcut. Then Eclipse offers me "Convert to indexed" for "loop" or "Convert to Iterator" for "loop".

Screenshot of quick fix options

+6
source

You can use either:

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

or manually:

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

But the first one that I prefer to use.

+1
source

Be careful with this refactoring.

The reason is that for a traditional linked list, your second for loop statement is O (N * N), since you need to go through the linked list to evaluate names.get(i); . It can become expensive.

Consider the impact of performance when migrating from for(String name:names) { . There may be a better way to correct your immediate mistake and save the current "big O".

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

is one such way (@JB Nizet Confirmation).

0
source

Do not go for indexed iteration! This does not work very well with all List implementations.

It’s much better to go for Iterator and let JIT optimize Iterator if this code is hot.

So write this:

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

Or what (one selection less):

 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); } 
0
source

When using java 8 you can use api stream

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

Something like that...

-2
source

Source: https://habr.com/ru/post/988560/


All Articles