Arrays
Problem
Thirty grades
A teacher writes a program for the test scores. For five students they make five variables:
int score1 = 62;int score2 = 85;int score3 = 47;int score4 = 91;int score5 = 78;int sum = score1 + score2 + score3 + score4 + score5;System.out.println(sum);363But the class has thirty students. Thirty variables, thirty terms to add. And the highest score needs twenty-nine more comparisons. The loop from the last lesson does not help: it cannot go through score1, score2, score3, because those are separate names. We need many values under one name.
The idea
An array: a row of boxes
An array is a row of values of one type under one name. Each value, an element of the array, has a number: its index. Indexes start at 0.
int[] scores = { 62, 85, 47, 91, 78 };System.out.println(scores[0]);System.out.println(scores[4]);System.out.println(scores.length);scores[2] = 50;System.out.println(scores[2]);6278550int[]is the type: "an array ofint". The values go in{ }.
scores[0]is the first element,scores[4]the fifth. The last index is always 1 less than the count.scores.lengthis the number of elements. Here it is 5.scores[2] = 50;changes one element. The others stay the same.
If you don't know the values yet, you create the array with just a size. Then all the elements are 0:
int[] booked = new int[3];booked[1] = 2;System.out.println(booked[0] + " " + booked[1] + " " + booked[2]);0 2 0The size is set when the array is created, and it does not change after that.
More precisely, if you are curious
- Indexes go only from 0 to the count minus 1. A negative index is outside the array.
Try it
Which is which?
What will the program print?
int[] prices = { 12, 7, 30, 5 };System.out.println(prices[1] + prices[3]);We count from 0: prices[1] is 7 (the second), prices[3] is 5 (the fourth). 7 + 5 = 12. If you count from 1, you will take 12 and 30.
The idea
A loop through the array
Now the loop does help. The counter i becomes the index: it goes from 0 to the last one and on every round takes scores[i].
int[] scores = { 62, 85, 47, 91, 78 };int sum = 0;for (int i = 0; i < scores.length; i++) { sum += scores[i];}System.out.println("Sum: " + sum);System.out.println("Average: " + (double) sum / scores.length);Sum: 363Average: 72.6The condition is i < scores.length, not a number. If you add all thirty grades in { }, the loop does not change. This is called traversing the array.
(double) is needed because of integer division: 363 / 5 is 72, and we need 72.6.
See it
The highest score
How do you find the biggest number? You remember the biggest one so far and replace it as soon as you see a bigger one.
int[] scores = { 62, 85, 47, 91, 78 };int max = scores[0];for (int i = 1; i < scores.length; i++) { if (scores[i] > max) { max = scores[i]; }}System.out.println(max); // 91Step by step, in words
- Five scores, side by side. The numbers below are the indexes: from 0 to 4.
- max starts from the first one: scores[0] is 62.
- i = 1: 85 > 62, so max becomes 85.
- i = 2: 47 is not bigger than 85. Nothing changes.
- i = 3: 91 > 85, so max becomes 91.
- i = 4: 78 < 91. Then i becomes 5, 5 < scores.length is false, and the loop stops.
- The highest score is 91.
max starts from the first element, not from 0. If all the scores were negative, 0 would "win" without being in the array. That is also why the loop starts from i = 1: the first one is already in max.
Try it
Find the bug
The program should print the sum 363. Instead it stops with an error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5Which line has the bug?
Pick the line with the bug.
<= the loop does one more round, with i = 5. The indexes of an array with 5 elements go from 0 to 4, and there is no element scores[5]. The program does not read someone else's memory: it stops with an error. This is called going outside the array. The fix is i < scores.length.The idea
for-each: for every element
When you need only the values and not the indexes, there is a shorter loop. How many students passed the exam (60 points or more)?
int[] scores = { 62, 85, 47, 91, 78 };int passed = 0;for (int score : scores) { if (score >= 60) { passed++; }}System.out.println("Passed the exam: " + passed);Passed the exam: 4It reads "for each score of scores". It is called for-each. There is no counter and no index, so you cannot go outside the array.
There is a limit too: you don't know which index you are at, and you cannot change the element.
More precisely, if you are curious
- If you write
score = 0;in the body, you change only the copy inscore. The array stays the same. The compiler does not stop you.
- To change elements, or when you need the index (for example for the neighbor
scores[i + 1]), use a regularfor.
Try it
Two names, one array
What will the program print?
int[] prices = { 10, 20, 30 };int[] sale = prices;sale[0] = 5;System.out.println(prices[0]);int b = a; copies the value. Arrays are different: sale = prices does not make a new array, it gives a second name to the same one. That is why a change through sale also shows through prices. Why this is so, you will learn in the module "Classes and objects": an array is an object, and the variable holds where it is.More precisely, if you are curious
You make a real copy with a new array and a loop:
int[] prices = { 10, 20, 30 };int[] sale = new int[prices.length];for (int i = 0; i < prices.length; i++) { sale[i] = prices[i];}sale[0] = 5;System.out.println(prices[0] + " " + sale[0]);10 5prices.clone() does the same.
Try it
Put the lines in order
The program should find the lowest price. Put its lines in order.
int[] prices = { 18, 7, 25, 12 };for (int i = 1; i < prices.length; i++) {}if (prices[i] < min) {min = prices[i];int min = prices[0];}System.out.println(min);
Exercise
Working with an array
Solve the exercises in your editor. Each program first reads how many numbers there are, then the numbers themselves, one per line:
Scanner in = new Scanner(System.in);int n = in.nextInt();int[] numbers = new int[n];for (int i = 0; i < n; i++) { numbers[i] = in.nextInt();}1. Sum, even, odd. Print the sum of all the numbers, of the even ones and of the odd ones.
3123Sum: 6Even: 2Odd: 42. Reversed. Create a new array with the same numbers in reverse order and print it on one line.
5123455 4 3 2 13. Lowest, highest, average. In one pass through the array.
549274Lowest: 2Highest: 9Average: 5.2Exercise
Sorting and counting
4. Sorting. Sort the numbers from the smallest to the biggest. Hint: go through the array, and if two neighbors are in the wrong order, swap them (swapping is from the lesson on variables). Repeat until there is nothing left to swap. This is called bubble sort: the big numbers "bubble up" to the end.
5427193253 7 19 25 425. Longest run. Find the longest run of equal numbers one after another.
822555155The number 5, 3 times in a row6. Grade statistics. Read grades from 2 to 6 and print how many there are of each kind. Hint: an array counts with 7 elements, where the grade is the index: counts[grade]++.
864563265Excellent (6): 3Very good (5): 2Good (4): 1Fair (3): 1Poor (2): 1More exercises
- Median. The number in the middle of the sorted array. For 3, 1, 4, 1, 5 the median is 3. If there is an even count of numbers, the median is the average of the two in the middle: for 7, 1, 3, 9 it is (3 + 7) / 2 = 5.
- Symmetric array. Does it read the same from front to back and from back to front? 1 2 3 2 1 is symmetric, 1 2 3 1 is not.
- Roman numerals. Read a number from 1 to 3999 and print it in Roman numerals: 2024 is MMXXIV, 1994 is MCMXCIV. Hint: two arrays side by side, with the values
1000, 900, 500, 400, 100, …, 1and with the symbols"M", "CM", "D", "CD", "C", …, "I". While the number is at least the current value, add the symbol and subtract the value.
Test