Java · lesson 7 of 66
Beginner
17- 1 Introduction to Java
- 2 Setting Up Java
- 3 Data Types in Java
- 4 Operators in Java
- 5 Variables and Operators in Java
- 6 Control Flow in Java
- 7 Arrays in Java
- 8 Functions (Methods) in Java
- 9 Strings in Java
- 10 Methods in Java
- 11 Java OOP — Complete Guide
- 12 Introduction to Object-Oriented Programming in Java
- 13 Encapsulation in Java
- 14 Inheritance in Java
- 15 Polymorphism in Java
- 17 Abstraction in Java
- 18 Error Types in Java
Intermediate
38- 16 Regular Expressions in Java
- 19 Interfaces in Java — A Deep Dive
- 20 Abstract Classes in Java
- 21 Method Overloading in Java
- 22 Composition vs Inheritance in Java
- 23 Generics in Java
- 27 Exception Handling in Java
- 28 Java Streams API
- 29 Collections Framework in Java
- 30 Optional in Java
- 31 File Handling in Java
- 32 Records in Java
- 33 Java 8 Features
- 34 Sealed Classes and Interfaces in Java
- 35 Multithreading in Java
- 37 JDBC — Database Access in Java
- 39 Maven — Java Build and Dependency Management
- 42 Gradle — Modern Java Build Tool
- 44 Unit Testing with JUnit 5 and Mockito
- 45 Logging in Java with SLF4J and Logback
- 49 Spring Boot — Introduction
- 50 Dependency Injection in Spring Boot
- 51 Java Project Ideas
- 52 Building REST APIs with Spring Boot
- 53 Validation in Spring Boot
- 54 Spring Data JPA — Database Access
- 55 Exception Handling in Spring Boot
- 56 Spring Security — Authentication and Authorization
- 57 JWT Authentication in Spring Boot
- 58 Dockerizing Spring Boot Applications
- 59 Java Enums: Beyond Simple Constants
- 60 Inner and Anonymous Classes in Java
- 61 Java Generics: Bounded Types, Wildcards, and Generic Methods
- 62 Java Date/Time API: LocalDate, LocalDateTime, and Duration
- 63 Java NIO.2: Paths, Files, and WatchService
- 64 Java Annotations: Custom Types and Meta-Information
- 65 Java Reflection: Dynamic Type Inspection and Method Invocation
- 66 Java Localization: ResourceBundle and Locale Support
Advanced
11Arrays in Java
Learn Java arrays — single and multi-dimensional arrays, array operations, sorting, searching, and the Arrays utility class.
By SkillByExample · Updated
An array is a fixed-size, ordered container of elements of one type. Arrays underpin
collections, sorting algorithms and matrices, and they are zero-indexed: the first element is at
index 0. Every example is a single file run with the JDK 21 source launcher (java File.java).
Creating arrays and default values
Create an array either with a size (Java fills it with defaults) or with the values inline.
import java.util.Arrays;
public class Create {
public static void main(String[] args) {
int[] scores = new int[3];
double[] temps = new double[2];
boolean[] flags = new boolean[2];
char[] letters = new char[2];
String[] names = new String[2];
int[] primes = {2, 3, 5, 7, 11};
System.out.println(Arrays.toString(scores));
System.out.println(Arrays.toString(temps));
System.out.println(Arrays.toString(flags));
System.out.println((int) letters[0]);
System.out.println(Arrays.toString(names));
System.out.println(Arrays.toString(primes) + " length=" + primes.length);
System.out.println(primes);
}
}
$ java Create.java
[0, 0, 0]
[0.0, 0.0]
[false, false]
0
[null, null]
[2, 3, 5, 7, 11] length=5
[I@20d3d15a
Numbers default to zero, boolean to false, references to null, and char to the character
with code 0 ('\u0000'), which is why it is printed as an int. The last line is what happens
without Arrays.toString: [I means “array of int”, and the hex part is an identity hash that
changes between runs.
Accessing elements and going out of bounds
Valid indices run from 0 to length - 1. One past the end compiles fine and fails at runtime.
public class Access {
public static void main(String[] args) {
int[] nums = {10, 20, 30, 40, 50};
System.out.println(nums[0]);
System.out.println(nums[nums.length - 1]);
nums[2] = 99;
System.out.println(nums[2]);
System.out.println(nums[5]);
}
}
$ java Access.java
10
50
99
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5
at Access.main(Access.java:8)
The first three lines printed before the crash. nums[nums.length - 1] is the safe way to reach
the last element without hard-coding the size.
Iterating
Use an index-based for when you need the position and the enhanced for when you only need
the values.
public class Iterate {
public static void main(String[] args) {
int[] scores = {85, 92, 78, 95, 88};
for (int i = 0; i < scores.length; i++) {
System.out.println("Score " + i + ": " + scores[i]);
}
int total = 0;
for (int s : scores) total += s;
System.out.println("Integer average: " + total / scores.length);
System.out.printf("Real average: %.1f%n", (double) total / scores.length);
}
}
$ java Iterate.java
Score 0: 85
Score 1: 92
Score 2: 78
Score 3: 95
Score 4: 88
Integer average: 87
Real average: 87.6
total / scores.length is int / int, so the .6 is thrown away. Casting one side to double
first keeps it.
The Arrays utility class
java.util.Arrays sorts, searches, fills, copies and compares, so you rarely write these loops
by hand.
import java.util.Arrays;
public class Utils {
public static void main(String[] args) {
int[] arr = {64, 25, 12, 22, 11};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
System.out.println("22 at " + Arrays.binarySearch(arr, 22));
System.out.println("23 at " + Arrays.binarySearch(arr, 23));
int[] copy = Arrays.copyOf(arr, arr.length);
int[] slice = Arrays.copyOfRange(arr, 1, 4);
System.out.println(Arrays.toString(slice));
System.out.println("equals: " + Arrays.equals(arr, copy) + ", same object: " + (arr == copy));
int[] sevens = new int[4];
Arrays.fill(sevens, 7);
System.out.println(Arrays.toString(sevens));
}
}
$ java Utils.java
[11, 12, 22, 25, 64]
22 at 2
23 at -4
[12, 22, 25]
equals: true, same object: false
[7, 7, 7, 7]
binarySearch returns -(insertion point) - 1 for a missing value: 23 would go at index 3, so
the result is -4. A copy has equal contents but is a different object, which is why equals
and == disagree. binarySearch only works on a sorted array; on an unsorted one its result is
undefined.
Arrays are references
Assigning an array to another variable copies the reference, not the elements.
import java.util.Arrays;
public class Alias {
public static void main(String[] args) {
int[] a = {1, 2, 3};
int[] b = a;
int[] c = a.clone();
b[0] = 100;
System.out.println("a = " + Arrays.toString(a));
System.out.println("c = " + Arrays.toString(c));
doubleAll(a);
System.out.println("a = " + Arrays.toString(a));
}
static void doubleAll(int[] arr) {
for (int i = 0; i < arr.length; i++) arr[i] *= 2;
}
}
$ java Alias.java
a = [100, 2, 3]
c = [1, 2, 3]
a = [200, 4, 6]
Writing through b changed a because both names point at one array; clone() made c an
independent copy. Passing an array to a method passes the same reference, so doubleAll changes
the caller’s array.
Two-pointer reverse
Swap from both ends toward the middle to reverse in place with no extra array.
import java.util.Arrays;
public class Reverse {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
int left = 0, right = arr.length - 1;
while (left < right) {
int temp = arr[left];
arr[left++] = arr[right];
arr[right--] = temp;
}
System.out.println(Arrays.toString(arr));
}
}
$ java Reverse.java
[5, 4, 3, 2, 1]
With five elements the pointers meet at index 2 and the loop stops; the middle element never moves.
2D arrays
A 2D array is an array of arrays: matrix[row][col]. matrix.length is the number of rows,
matrix[r].length the length of row r.
import java.util.Arrays;
public class Grid {
public static void main(String[] args) {
int[][] matrix = {
{1, 2, 3},
{4, 5, 6}
};
System.out.println(matrix[1][2] + " rows=" + matrix.length + " cols=" + matrix[0].length);
for (int[] row : matrix) {
for (int v : row) System.out.printf("%3d", v);
System.out.println();
}
System.out.println(Arrays.toString(matrix));
System.out.println(Arrays.deepToString(matrix));
}
}
$ java Grid.java
6 rows=2 cols=3
1 2 3
4 5 6
[[I@212bf671, [I@14a2f921]
[[1, 2, 3], [4, 5, 6]]
Arrays.toString on a 2D array prints the inner array references; deepToString recurses into them.
Jagged arrays
Rows do not have to be the same length. Create the outer array with only the row count and assign each row separately.
import java.util.Arrays;
public class Jagged {
public static void main(String[] args) {
int[][] triangle = new int[4][];
for (int r = 0; r < triangle.length; r++) {
triangle[r] = new int[r + 1];
triangle[r][0] = triangle[r][r] = 1;
for (int c = 1; c < r; c++) {
triangle[r][c] = triangle[r - 1][c - 1] + triangle[r - 1][c];
}
}
for (int[] row : triangle) System.out.println(Arrays.toString(row));
}
}
$ java Jagged.java
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
Each row of Pascal’s triangle is one longer than the last, so a rectangular int[4][4] would
waste space; new int[4][] leaves every row null until it is assigned.
Project: student marks
Parallel arrays hold the names and marks; the input comes from command-line arguments.
public class StudentMarks {
public static void main(String[] args) {
int n = args.length / 2;
String[] names = new String[n];
int[] marks = new int[n];
for (int i = 0; i < n; i++) {
names[i] = args[2 * i];
marks[i] = Integer.parseInt(args[2 * i + 1]);
}
int top = 0, total = 0;
for (int i = 0; i < n; i++) {
total += marks[i];
if (marks[i] > marks[top]) top = i;
}
System.out.printf("Class average: %.1f%n", (double) total / n);
System.out.printf("Top scorer: %s (%d)%n", names[top], marks[top]);
}
}
$ java StudentMarks.java Alice 78 Bob 92 Charlie 85
Class average: 85.0
Top scorer: Bob (92)
args is itself a String[]. Index 2 * i holds a name and 2 * i + 1 its mark, so the two
arrays stay aligned by position — the weakness of parallel arrays is that a sort must move both
in lockstep (Practice task 4).
Practice
- Rotate an array left by one position in place, so
{1, 2, 3, 4, 5}becomes{2, 3, 4, 5, 1}.
Solution
import java.util.Arrays;
public class RotateLeft {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
int first = arr[0];
for (int i = 0; i < arr.length - 1; i++) arr[i] = arr[i + 1];
arr[arr.length - 1] = first;
System.out.println(Arrays.toString(arr));
}
}
$ java RotateLeft.java
[2, 3, 4, 5, 1]
Saving arr[0] before the shift overwrites it is what makes the in-place rotation work.
- Find the second-largest distinct value in
{4, 2, 9, 7, 9, 1}in one pass, without sorting.
Solution
public class SecondLargest {
public static void main(String[] args) {
int[] nums = {4, 2, 9, 7, 9, 1};
int max = Integer.MIN_VALUE, second = Integer.MIN_VALUE;
for (int n : nums) {
if (n > max) { second = max; max = n; }
else if (n > second && n != max) second = n;
}
System.out.println("max=" + max + " second=" + second);
}
}
$ java SecondLargest.java
max=9 second=7
When a new max arrives, the old max becomes the second; n != max stops the duplicate 9 from
also becoming the second-largest.
- Sum every element of the jagged array
{{1}, {2, 3}, {4, 5, 6}}and print each row’s sum too.
Solution
public class SumJagged {
public static void main(String[] args) {
int[][] jagged = {{1}, {2, 3}, {4, 5, 6}};
int total = 0;
for (int[] row : jagged) {
int rowSum = 0;
for (int v : row) rowSum += v;
System.out.println("row sum " + rowSum);
total += rowSum;
}
System.out.println("total " + total);
}
}
$ java SumJagged.java
row sum 1
row sum 5
row sum 15
total 21
The enhanced for never reads a row’s length explicitly, so different row lengths need no special case.
- Extend
StudentMarksto print a ranking from highest to lowest mark, keeping each name with its mark.
Solution
public class Ranking {
public static void main(String[] args) {
String[] names = {"Alice", "Bob", "Charlie"};
int[] marks = {78, 92, 85};
for (int i = 0; i < marks.length - 1; i++) { // selection sort, descending
int best = i;
for (int j = i + 1; j < marks.length; j++) if (marks[j] > marks[best]) best = j;
int m = marks[i]; marks[i] = marks[best]; marks[best] = m;
String s = names[i]; names[i] = names[best]; names[best] = s;
}
for (int i = 0; i < marks.length; i++) {
System.out.printf("%d. %s (%d)%n", i + 1, names[i], marks[i]);
}
}
}
$ java Ranking.java
1. Bob (92)
2. Charlie (85)
3. Alice (78)
Every swap in marks is mirrored in names; forget one and the names drift away from their
marks. That fragility is why real code puts both in one object (a record Student(String name, int mark)) and sorts an array of those.
- Add two 2×3 matrices element by element and print the result with
Arrays.deepToString.
Solution
import java.util.Arrays;
public class MatrixAdd {
public static void main(String[] args) {
int[][] a = {{1, 2, 3}, {4, 5, 6}};
int[][] b = {{7, 8, 9}, {1, 2, 3}};
int[][] sum = new int[a.length][a[0].length];
for (int i = 0; i < a.length; i++)
for (int j = 0; j < a[i].length; j++)
sum[i][j] = a[i][j] + b[i][j];
System.out.println(Arrays.deepToString(sum));
}
}
$ java MatrixAdd.java
[[8, 10, 12], [5, 7, 9]]
The result array is created with the same shape as the inputs; new int[rows][cols] starts it at all zeros.