# Java Loops and Iteration

## Iterate between two numbers

Using **while loop**:

```java
int i = 0;
while (i < 10) {
  System.out.println(i);
  i++;
}
```

Using **for loop**:

```java
for (int i = 0; i < 10; i++) {
  System.out.println(i);
}
```

Using **do-while loop**:

```java
int i = 0;
do {
  System.out.println(i);
  i++;
} while (i < 10);
```

Using **IntStream** with **range()** - supported in Java 8 and higher:

```java
import java.util.stream.IntStream;

IntStream.range(0, 10).forEach(System.out::println);
```

Using **IntStream** with **iterate()** and **limit()** - supported in Java 8 and higher:

```java
import java.util.stream.IntStream;

IntStream.iterate(0, i -> i + 1).limit(10).forEach(System.out::println);
```

More about Streams in the [Streams cheatsheet](https://fosseryweb.codeberg.page/cheatsheets/java/streams.html).

### Iterate backwards

Using **while loop**:

```java
int i = 9;
while (i >= 0) {
  System.out.println(i);
  i--;
}
```

Using **for loop**:

```java
for (int i = 9; i >= 0; i--) {
  System.out.println(i);
}
```

Using **do-while loop**:

```java
int i = 9;
do {
  System.out.println(i);
  i--;
} while (i >= 0);
```

Using **IntStream** with **iterate()** and **limit()** - supported in Java 8 and higher:

```java
import java.util.stream.IntStream;

IntStream.iterate(9, i -> i - 1).limit(10).forEach(System.out::println);
```

More about Streams in the [Streams cheatsheet](https://fosseryweb.codeberg.page/cheatsheets/java/streams.html).

## Iterate through characters of a String

Using **while loop**:

```java
String hello = "Hello World";
int i = 0;
while (i < hello.length()) {
  System.out.println(hello.charAt(i));
  i++;
}
```

Using **for loop**:

```java
for (int i = 0; i < hello.length(); i++) {
  System.out.println(hello.charAt(i));
}
```

Using performance-optimized **for loop** - length only calculated once:

```java
for (int i = 0, n = hello.length(); i < n; i++) {
  System.out.println(hello.charAt(i));
}
```

Using **enhanced (for each) loop** - note that it can't be applied directly on a String, conversion to an array is needed!:

```java
for (char character : hello.toCharArray()) {
  System.out.println(character);
}
```

### Iterate backwards

Using **while loop**:

```java
// hello = "Hello World";
int i = hello.length() - 1;
while (i >= 0) {
  System.out.println(hello.charAt(i));
  i--;
}
```

Using **for loop**:

```java
for (int i = hello.length() - 1; i >= 0; i--) {
  System.out.println(hello.charAt(i));
}
```

## Iterate through an array

Using **while loop**:

```java
String[] shoppingList = new String[]{"bread", "carrot", "chocolate", "apple"};
int i = 0;
while (i < shoppingList.length) {
  System.out.println(shoppingList[i]);
  i++;
}
```

Using **for loop**:

```java
for (int i = 0; i < shoppingList.length; i++) {
  System.out.println(shoppingList[i]);
}
```

Using performance-optimized **for loop** - length only calculated once:

```java
for (int i = 0, n = shoppingList.length; i < n; i++) {
  System.out.println(shoppingList[i]);
}
```

Using **enhanced (for each) loop**:

```java
for (String item : shoppingList) {
  System.out.println(item);
}
```

Using **Arrays.stream()** - note that original array can't be modified this way! - supported in Java 8 and higher:

```java
import java.util.Arrays;

Arrays.stream(shoppingList).forEach(item -> System.out.println(item));
```

More about Streams in the [Streams cheatsheet](https://fosseryweb.codeberg.page/cheatsheets/java/streams.html).

### Iterate backwards

Using **while loop** to loop backwards:

```java
// shoppingList = new String[]{"bread", "carrot", "chocolate", "apple"};
int i = shoppingList.length - 1;
while (i >= 0) {
  System.out.println(hello[i]);
  i--;
}
```

Using **for loop** to loop backwards:

```java
for (int i = shoppingList.length - 1; i >= 0; i--) {
  System.out.println(shoppingList[i]);
}
```

## Iterate through a collection

Using **while loop**:

```java
import java.util.List;
import java.util.Arrays;

List<String> shoppingList = Arrays.asList("bread", "carrot", "chocolate", "apple");
int i = 0;
while (i < shoppingList.size()) {
  System.out.println(shoppingList.get(i));
  i++;
}
```

Using **for loop**:

```java
for (int i = 0; i < shoppingList.size(); i++) {
  System.out.println(shoppingList.get(i));
}
```

Using performance-optimized **for loop** - size only calculated once:

```java
for (int i = 0, n = shoppingList.size(); i < n; i++) {
  System.out.println(shoppingList.get(i));
}
```

Using **enhanced (for each) loop**:

```java
for (String item : shoppingList) {
  System.out.println(item);
}
```

Using **forEach()** - note that collection can't be modified this way!:

```java
shoppingList.forEach(item -> System.out.println(item));
```

Using **Iterator** with **while loop, hasNext() and next()**:

```java
import java.util.Iterator;

// shoppingList = Arrays.asList("bread", "carrot", "chocolate", "apple");
Iterator<String> it = shoppingList.iterator();
while (it.hasNext()) {
  System.out.println(it.next());
}
```

Using **Iterator** with **forEachRemaining()** - supported in Java 8 and higher:

```java
Iterator<String> iter = shoppingList.iterator();
iter.forEachRemaining(listItem -> System.out.println(listItem));
```

Using **ListIterator** with **while loop, hasNext() and next()** - only works with Lists:

```java
import java.util.ListIterator;

ListIterator<String> it = shoppingList.listIterator();
while (it.hasNext()) {
  System.out.println(it.next());
}
```

Using **Stream** - note that original collection can't be modified this way! - supported in Java 8 and higher:

```java
shoppingList.stream().forEach(item -> System.out.println(item));
```

More about Streams in the [Streams cheatsheet](https://fosseryweb.codeberg.page/cheatsheets/java/streams.html).

### Iterate backwards

Using **while loop**:

```java
// shoppingList = Arrays.asList("bread", "carrot", "chocolate", "apple");
int i = shoppingList.size() - 1;
while (i >= 0) {
  System.out.println(shoppingList.get(i));
  i--;
}
```

Using **for loop**:

```java
for (int i = shoppingList.size() - 1; i >= 0; i--) {
  System.out.println(shoppingList.get(i));
}
```

Using **enhanced (for each) loop** and **Collections.reverse()** - note that a separate collection is created, items of original collection can't be accessed directly - lower performance due to new (reversed) collection being created:

```java
import java.util.Collections;

Collections.reverse(shoppingList);
for (String item : shoppingList) {
  System.out.println(item);
}
```

Using **enhanced (for each) loop** and **List.reversed()** - same issues as with previous one, plus only works with Lists, only supported in Java 21 and higher:

```java
for (String item : shoppingList.reversed()) {
  System.out.println(item);
}
```

Using **ListIterator** with **while loop, hasPrevious() and previous()** - note that the size of the List need to be passed when creating ListIterator, to use reverse iteration - only works with Lists:

```java
import java.util.ListIterator;

ListIterator<String> it = shoppingList.listIterator(shoppingList.size());
while (it.hasPrevious()) {
  System.out.println(it.previous());
}
```

Using **Stream** with **descendingIterator()** - lower performance due to additional ArrayDeque being created:

```java
import java.util.Collectors;
import java.util.ArrayDeque;

shoppingList.stream()
        .collect(Collectors.toCollection(ArrayDeque::new))
        .descendingIterator()
        .forEachRemaining(System.out::println);
```

More about Streams in the [Streams cheatsheet](https://fosseryweb.codeberg.page/cheatsheets/java/streams.html).
