Looping over an array and Arrays
An array is rarely read one element at a time. Usually you need to do something with all its elements at once: add them up, print them, sort them.
Let's go back to the row of lockers. To check every locker, you walk along the row from the first to the last and open each one in turn. For an array, a loop takes that walk: on each lap it takes the next index. Let's add up the scores:
public class Main {
public static void main(String[] args) {
int[] scores = {90, 75, 60};
int sum = 0;
for (int i = 0; i < scores.length; i++) {
sum = sum + scores[i];
}
System.out.println(sum); // 225
}
}Let's walk through the program line by line:
int sum = 0;sets up the sum, zero for now.for (int i = 0; i < scores.length; i++)goes through the indices0,1and2: exactly as many laps as there are elements in the array.sum = sum + scores[i];adds the element at the current index to the sum.- After the loop,
System.out.println(sum)prints225.
The index loop
This loop has three rules:
- counting starts at
0, the first index; - the condition is
i < scores.length, strictly less: the last index is one less than the length; - through the index you can change elements as well as read them:
scores[i] = scores[i] * 2;doubles the current element.
With the condition i <= scores.length the loop makes one extra lap. On it i becomes 3, and reading scores[3] throws an ArrayIndexOutOfBoundsException.
The for-each loop
When you do not need the index, there is a shorter form. The for-each loop puts each element of the array into a variable in turn, from the first to the last. The same sum with it looks like this:
int total = 0;
for (int x : scores) {
total = total + x;
}
System.out.println(total); // 225The header for (int x : scores) reads as "for each x in scores":
int xis the variable for the current element; its type matches the type of the elements;- the colon separates the variable from the array;
scoresis the array the loop goes through.
There is no counter, condition or step here: the loop itself knows where the array starts and ends. So it cannot step past the end.
The variable x gets a copy of the element, the same way b in int b = a gets a copy of the number. It is an ordinary variable: you can change it, say by writing x = 0. But the array does not change because of it. It is like copying a number from a locker into a notebook: a correction in the notebook does not change what lies in the locker. So for-each is for reading elements, and to change them you need the index loop.
Imports and the Arrays class
The Java standard library is thousands of ready-made classes. They are sorted into packages, like books on shelves: each class has a full name made of the package name and its own name. The Arrays class with tools for arrays sits in the package java.util, and its full name is java.util.Arrays.
The classes System, String and Integer sit in the package java.lang. Java brings that package into every program by itself, which is why we have not had to bring in anything so far. For a class from another package, you write an import at the start of the file, before public class Main:
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] scores = {90, 75, 60};
System.out.println(Arrays.toString(scores)); // [90, 75, 60]
Arrays.sort(scores);
System.out.println(Arrays.toString(scores)); // [60, 75, 90]
}
}Here the shelf picture is off: an import does not take the class off the shelf or copy its code into the program. It only tells the compiler that the short name Arrays means java.util.Arrays. Without that line the compiler does not know the name Arrays and stops with the error cannot find symbol, the same one as for an undeclared variable.
Arrays.toString
Arrays.toString(scores) builds a string from the elements, in square brackets and separated by commas: [90, 75, 60]. It is handy to print when you need to see the whole array at once.
You cannot do without this method. The line System.out.println(scores) prints not the elements but a service note like [I@ followed by a mix of digits and letters. That is a code for the type and an internal number of the array, and it can change from run to run.
Arrays.sort
Arrays.sort(scores) sorts the elements in ascending order. It changes the array itself instead of creating a new one, and it returns nothing. So the call is written as a statement of its own, and you look at the result through Arrays.toString. The line System.out.println(Arrays.sort(scores)) does not compile.
Common mistake
You wanted to double all the prices and wrote the new value into the for-each variable:
int[] prices = {10, 20, 30};
for (int p : prices) {
p = p * 2; // ✗
}
System.out.println(Arrays.toString(prices)); // [10, 20, 30]The program compiles and prints [10, 20, 30]: the prices did not change. Each lap doubled the copy of the element in the variable p, and the array stayed as it was. To change the elements, you need the index loop: prices[i] = prices[i] * 2;.
Key points
- The index loop starts at
0with the conditioni < a.length; througha[i]elements can be read and changed. - The for-each loop
for (int x : a)puts a copy of each element intox: writing toxdoes not change the array. - A class from another package is brought in with an import at the start of the file:
import java.util.Arrays;. Arrays.toStringturns an array into the string[90, 75, 60], andArrays.sortsorts the array itself in ascending order.