While for each java

for-each vs for vs while

I wonder what is the best way to implement a «for-each» loop over an ArrayList or every kind of List. Which of the followings implementations is the best and why? Or is there a best way? Thank you for your help.

List values = new ArrayList();

values.add(«one»); values.add(«two»); values.add(«three»); .

//#0
for(String value : values)

//#1
for(int i = 0; i

//#2
for(Iterator it = values.iterator(); it.hasNext(); )

//#3
Iterator it = values.iterator(); while (it.hasNext())

4 Answers 4

#3 has a disadvantage because the scope of the iterator it extends beyond the end of the loop. The other solutions don’t have this problem.

#2 is exactly the same as #0, except #0 is more readable and less prone to error.

#1 is (probably) less efficient because it calls .size() every time through the loop.

#0 is usually best because:

  • it is the shortest
  • it is least prone to error
  • it is idiomatic and easy for other people to read at a glance
  • it is efficiently implemented by the compiler
  • it does not pollute your method scope (outside the loop) with unnecessary names

Nice answer. However, #1 is required when updating (if not just mutating the current item or building the results as a new list) and comes with the index. Since the List<> is an ArrayList<> in this case, the get() (and size() ) is O(1) , but that isn’t the same for all List-contract types.

The short answer is to use version 0. Take a peek at the section title Use Enhanced For Loop Syntax at Android’s documentation for Designing for Performance. That page has a bunch of goodies and is very clear and concise.

That is for android but in this question there is no Android TAG, and also it depends in what you need at the end.

#0 is the easiest to read, in my opinion, but #2 and #3 will work just as well. There should be no performance difference between those three.

In almost no circumstances should you use #1. You state in your question that you might want to iterate over «every kind of List». If you happen to be iterating over a LinkedList then #1 will be n^2 complexity: not good. Even if you are absolutely sure that you are using a list that supports efficient random access (e.g. ArrayList ) there’s usually no reason to use #1 over any of the others.

It’s not true that #1 should never be used. It is the only way to change the cell of a List that pass, although the time complexity (which is not implied with List) must be considered.

for (int i = 0; i < x.size(); i++) < x.set(i, i * 2); >Granted that’s a silly example and in many cases just creating a new List is better. Also, it might be more appropriate to restrict to ArrayList in such cases. But it is a counter to never.

Right. Fair enough. Although I’d still suggest using a ListIterator and it’s set method in preference. Then it will still efficiently work with non-random-access lists.

In response to this comment from the OP.

However, #1 is required when updating (if not just mutating the current item or building the results as a new list) and comes with the index. Since the List<> is an ArrayList<> in this case, the get() (and size()) is O(1), but that isn’t the same for all List-contract types.

Lets look at these issues:

It is certainly true that get(int) is not O(1) for all implementations of the List contract. However, AFAIK, size() is O(1) for all List implementations in java.util . But you are correct that #1 is suboptimal for many List implementations. Indeed, for lists like LinkedList where get(int) is O(N) , the #1 approach results in a O(N^2) list iteration.

In the ArrayList case, it is a simple matter to manually hoist the call to size() , assigning it to a (final) local variable. With this optimization, the #1 code is significantly faster than the other cases . for ArrayList s.

Your point about changing the list while iterating the elements raises a number of issues:

  • If you do this with a solution that explicitly or implicitly uses iterators, then depending on the list class you may get ConcurrentModificationException s. If you use one of the concurrent collection classes, you won’t get the exception, but the javadocs state that the iterator won’t necessarily return all of the list elements.
  • If you do this using the #1 code (as is) then, you have a problem. If the modification is performed by the same thread, you need to adjust the index variable to avoid missing entries, or returning them twice. Even if you get everything right, a list entry concurrently inserted before the current position won’t show up.
  • If the modification in the #1 case is performed by a different thread, it hard to synchronize properly. The core problem is that get(int) and size() are separate operations. Even if they are individually synchronized, there is nothing to stop the other thread from modifying the list between a size and get call.

In short, iterating a list that is being concurrently modified is tricky, and should be avoided . unless you really know what you are doing.

Источник

Iterate with for loop or while loop?

I think code should be as simple to understand as possible so that I only have to make complex code to do complex things. What do you think? Which is better?

15 Answers 15

I prefer the for loop because it also sets the scope of the iterator to just the for loop.

Note that since Java 6, the preferred idiom for iterating (if you don’t need index loop) is: for (MyClass elem : list) < //do something with elem >I comment here because this comes up with some google searches.

There are appropriate uses for the while, the for, and the foreach constructs:

  • while — Use this if you are iterating and the deciding factor for looping or not is based merely on a condition. In this loop construct, keeping an index is only a secondary concern; everything should be based on the condition
  • for — Use this if you are looping and your primary concern is the index of the array/collection/list. It is more useful to use a for if you are most likely to go through all the elements anyway, and in a particular order (e.g., going backwards through a sorted list, for example).
  • foreach — Use this if you merely need to go through your collection regardless of order.

Obviously there are exceptions to the above, but that’s the general rule I use when deciding to use which. That being said I tend to use foreach more often.

I wish I could give this extra points for addressing the structural meaning of the loop types. Thank you!

Why not use the for-each construct? (I haven’t used Java in a while, but this exists in C# and I’m pretty sure Java 1.5 has this too):

List names = new ArrayList(); names.add("a"); names.add("b"); names.add("c"); for (String name : names) System.out.println(name.charAt(0)); 

The one time you can’t use this construct is if you need to call Iterator.remove(), since the iterator is only ever inferred, not explicit.

I think scope is the biggest issue here, as you have pointed out.

In the «while» example, the iterator is declared outside the loop, so it will continue to exist after the loop is done. This may cause issues if this same iterator is used again at some later point. E. g. you may forget to initialize it before using it in another loop.

In the «for» example, the iterator is declared inside the loop, so its scope is limited to the loop. If you try to use it after the loop, you will get a compiler error.

Источник

Циклы в Java

Java-университет

Циклы в Java - 1

Программа, написанная на языке Java, состоит из определенного кода. Обычно он выполняется последовательно: строка за строкой, сверху вниз. Но есть и такие конструкции кода, которые меняют линейное выполнение программы. Их называют управляющими конструкциями. Благодаря им, код можно выполнять выборочно. Например, запустить один блок кода вместо другого. Циклы — это разновидность управляющих конструкций для организации многократного выполнения одного и того же участка кода. Код внутри такой управляющей конструкции выполняется циклично. Каждое выполнение кода — это итерация цикла. Количество итераций регулируется условием цикла. Код, который выполняется внутри цикла, называют телом цикла. Известны такие виды циклов:

  1. Циклы с предусловием: условие выполнения определяется перед первой итерацией.
  2. Циклы с постусловием: условие выполнения определяется после первой итерации (поэтому они всегда выполняются минимум один раз). Полезны, когда нужно выполнять некое действие, пока не реализуется некое условие: например, считывать ввод пользователя, пока он не введет слово “stop”.
  3. Циклы со счетчиком: количество итераций определяется смоделированным счетчиком. В условии цикла задается его начальное и конечное значение. Каждую итерацию счетчик наращивается. Мы можем заранее определить количество итераций. Эти циклы бывают полезны, когда нужно перебрать все элементы в какой-то коллекции. Циклы со счетчиком называют “циклами для. ”. “Для каждого элемента некоторой коллекции осуществить следующие действия”. Допустимы случаи, когда выполнение цикла можно прервать до достижения его условия. Например, если у нас есть коллекция из 100 чисел и нам необходимо понять, содержит ли она отрицательные числа. Мы можем начать перебор всех чисел, используя цикл “для”. Но когда мы найдем первое отрицательное число, нам не обязательно перебирать оставшиеся числа. Мы можем прервать выполнение цикла, если его дальнейшее выполнение не имеет смысла. Подобные ситуации называют прерыванием цикла.
  4. Безусловные циклы — циклы, которые выполняются бесконечно. Например: “Пока 1=1, печатать “1=1””. Такая программа будет выполняться, пока ее вручную не прервут. Данные циклы тоже бывают полезны, когда используются вместе с прерыванием цикла “изнутри”. Используйте их осторожно, чтобы не спровоцировать зависание программы. Подробнее с циклами в языке программирования Java можно познакомиться на 4-ом уровне курса JavaRush. В частности, с циклами while и for.

Циклы в Java

  • while — цикл с предусловием;
  • do..while — цикл с постусловием;
  • for — цикл со счетчиком (цикл для);
  • for each.. — цикл “для каждого…” — разновидность for для перебора коллекции элементов.

Цикл while

  • expression — условие цикла, выражение, которое должно возвращать boolean значение.
  • statement(s) — тело цикла (одна или более строк кода).
 public class WhileExample < public static void main(String[] args) < int countDown = 10; while (countDown >= 0) < System.out.println("До старта: " + countDown); countDown --; >System.out.println("Поехали !"); > > 
 До старта: 10 До старта: 9 До старта: 8 До старта: 7 До старта: 6 До старта: 5 До старта: 4 До старта: 3 До старта: 2 До старта: 1 До старта: 0 Поехали ! 
 public class WhileExample < public static void main(String[] args) < int count = 1; while (true) < System.out.println("Строка №" + count); if (count >3) < break; >count++; // Без наращивания цикл будет выполняться вечно > > > 
 Строка №1 Строка №2 Строка №3 Строка №4 

Цикл do..while

  • expression — условие цикла, выражение, которое должно возвращать boolean значение.
  • statement(s) — тело цикла (одна или более строк кода).
 public class DoWhileExample < public static void main(String[] args) < int count = 1; do < System.out.println("count lang-java line-numbers"> for (initialization; termination; increment)
  • initialization — выражение, которое инициализирует выполнение цикла. Исполняется только раз в начале цикла. Чаще всего в данном выражении инициализируют счетчик цикла
  • termination — boolean выражение, которое регулирует окончание выполнения цикла. Если результат выражения будет равен false, цикл for прервется.
  • increment — выражение, которое исполняется после каждой итерации цикла. Чаще всего в данном выражении происходит инкрементирование или декрементирование переменной счетчика.
  • statement(s) — тело цикла.
 Строка №1 Строка №2 Строка №3 Строка №4 Строка №5 

Цикл for each

Этот цикл Java — разновидность цикла for для итерации коллекций и массивов. Структура for each выглядит так:

  • vars — переменная, существующий список или массив
  • Type var — определение новой переменной того же типа ( Type ), что и коллекция vars .
 public class ForExample < public static void main(String[] args) < String[] daysOfWeek = < "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресенье" >; for (String dayOfWeek : daysOfWeek) < System.out.println(dayOfWeek); >> > 

Циклы в Java - 2

Циклы Java изучаются на курсе JavaRush на четвертом уровне квеста Java Syntax. Попробуйте свои силы в решении задач по этой теме 🙂

Источник

Читайте также:  The java mouse deer
Оцените статью