As you've seen, you can get pretty far with "scalar" data. But many phenomena we wish to model computationally are aggregates, or collections, for example:
Today we'll learn Java's most basic facility for modeling aggregates: arrays.
Java Arrays ():
new
), andConsider the following array creation expression JLS 10.3:
double[] scores = new double[5];
This declaration:
5
in the example above can be any expression that is unary promotable to an int
JLS 5.6.1scores
, and0
for numeric types, false
for boolean
types, and null
for references JLS 4.12.5.The preceding array definition
double[] scores = new double[5];
could be split into a declaration and initialization:
double[] scores;
scores = new double[5];
Can put the []
on the type or the variable. These two declarations are equivalent:
double[] scores;
double scores[];
Better style to put the []
on the type.
Can mix array and variable declarations when element type same as variable type. The declaration line:
double scores[], average;
creates
double
reference named scores
, anddouble
variable named average
What's the size of the scores
array declared above?
After the definition:
double[] scores = new double[5];
scores
points to an array object that can be visualized as:
scores
range from 0 to 4.public final
instance variable named length
scores.length == 5;
What is the type and value of the expression above?
Array elements addressed with int
-promotable expression in square brackets ([]
)
double[] scores = new double[5];
scores[0] = 89;
scores[1] = 100;
scores[2] = 95.6;
scores[3] = 84.5;
scores[4] = 91;
scores[scores.length - 1] = 99.2;
Will this line compile? If so, what will happen at runtime?
scores[scores.length] = 100;
You can provide initial values for (small) arrays
String[] validSuits = {"diamonds", "clubs", "hearts","spades"};
validSuits.length
?validSuits[1]
?You can also use a loop to initialize the values of an array:
int[] squares = new int[5];
for (int i = 0; i < squares.length; ++i) {
squares[i] = i*i;
}
What is squares[4]
?
Arrays and for
go hand-in-hand:
double[] scores = new double[5];
for (int i = 0; i < 5; ++i) {
System.out.printf("scores[%d] = %.2f%n", i, scores[i]);
}
Can also use the "enhanced" for:
for (double score: scores) {
System.out.println(score);
}
Read the enhanced for as "for each element in array ...".
Why use for-each instead of traditional for? ...
for
Versus for
-eachIf you don't need the index, use the enhanced for loop.
double sum = 0.0;
for (int i = 0; i < scores.length; ++i) {
sum += scores[i];
}
scores.length
is used only for bounding the array traversali
is only used for sequential array access.Those are two things we can mess up.
for
The enhanced for loop is cleaner:
double sum = 0.0;
for (double score: scores) {
sum += score;
}
Also note how our naming conventions help to make the code clear. You can read the loop above as "for each score in scores".
Because arrays are allocated dynamically, this will compile:
double[] scores = new double[-5];
because the compiler only checks that -5
is an int
expression, but the code will produce an error at run-time:
Exception in thread "main" java.lang.NegativeArraySizeException
at ArrayBasics.main(ArrayBasics.java:4)
Array access expressions are also merely type-checked at compile time but are evaluated and checked for validity at run-time. Negative indexes like:
scores[-1] = 100;
produce:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at ArrayBasics.main(ArrayBasics.java:23)
... just like an index too large for the array would fail.
We've already seen an array parameter:
public static void main(String[] args)
We can use this array just like we use any other array.
public class Shout {
public static void main(String[] args) {
for (String arg: args) {
System.out.print(arg.toUpperCase() + " ");
System.out.println();
}
See also CourseAverage.java
...
) after the type name.public static int max(int ... numbers)
Var args parameter is an array inside the method.
public static int max(int ... numbers) {
int max = numbers[0];
for (int i = 1; i < numbers.length; ++i) {
if (numbers[i] > max) max = number;
}
return max;
}
You can create multidimensional arrays by adding additional square brackets for dimensions and sizes.
char[][] grid;
char
char
is the element typegrid
, which is indexed by two int
expressions, is a char
variableWith new
:
grid = new char[10][10];
char[][] grid = {{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
{' ', '*', '*', ' ', ' ', ' ', ' ', '*', '*', ' '},
{' ', '*', '*', ' ', ' ', ' ', ' ', '*', '*', ' '},
{' ', ' ', ' ', ' ', '*', '*', ' ', ' ', ' ', ' '},
{' ', ' ', ' ', ' ', '*', '*', ' ', ' ', ' ', ' '},
{' ', '*', ' ', ' ', ' ', ' ', ' ', ' ', '*', ' '},
{' ', ' ', '*', ' ', ' ', ' ', ' ', '*', ' ', ' '},
{' ', ' ', ' ', '*', '*', '*', '*', ' ', ' ', ' '},
{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}};
A 2-d array is an array of 1-d arrays
grid
array can be visualized as a 2-d grid of cells.
Individual element addressed by supplying two indices:
grid[3][2] == '*'; // true
Traverse 2-dimensional array by nesting loops. Key is to use the right length
s. Row-major traversal:
for (int row = 0; row < grid.length; ++row) {
for (int col = 0; col < grid[row].length; ++col) {
System.out.print(grid[row][col]);
}
System.out.println();
}
Column-major traversal:
for (int col = 0; col < grid[0].length; ++col) {
for (int row = 0; row < grid.length; ++row) {
System.out.print(grid[row][col]);
}
System.out.println();
}
See Smiley.java
new
and array variables can have the value null
.