Java • Collections and Strings

Array Iteration & Aggregates — Iterate through arrays and compute aggregates

Learn to traverse arrays with loops and compute sums, averages, min, max, and counts in Java.

Java programming emblem with a coffee cup, code braces, and terminal
Inside this lesson 10 sections 5 questions 10 figures

SECTION 1

Historical Context & Motivation

Long before modern programming languages existed, mathematicians and scientists needed ways to process collections of numbers — computing totals, finding extremes, and summarizing large data sets. When early computers emerged in the 1940s and 1950s, one of the first problems programmers tackled was how to store and process sequences of values efficiently. The concept of an array — a fixed-size block of memory holding elements of the same type — became the foundational data structure for solving these problems.

As programming languages evolved, the idea of iteration — stepping through each element of a collection one by one — became central to how we work with data. Whether you are calculating a student's grade average, finding the highest score in a game, or counting how many sensor readings exceed a threshold, iteration over arrays is the tool that makes it possible. Java, released in 1995, carried these ideas forward with clean syntax and strong type safety.

1945 • Arrays in Early Computing

Konrad Zuse's Plankalkül language introduced the idea of indexed storage — the predecessor to arrays — enabling repeated operations on sequences of numbers.

1957 • FORTRAN Formalizes Arrays

IBM's FORTRAN became the first widely used language to support arrays and DO loops, allowing scientists to iterate through data sets systematically.

1972 • C Popularizes Array Indexing

The C language introduced zero-based array indexing (starting from index 0), a convention that Java would later adopt directly.

1995 • Java Launches with Built-in Arrays

Java included arrays as first-class objects with bounds checking and a .length property, making iteration safer and more predictable than in C.

2004 • Enhanced for Loop (for-each)

Java 5 introduced the enhanced for loop, simplifying array iteration by eliminating the need for manual index management.

The core question this lesson addresses is: given a collection of values stored in an array, how do we visit each element and compute useful summary values — called aggregates — such as sums, averages, minimums, maximums, and counts? Mastering this pattern is essential because nearly every real-world program processes collections of data.

SECTION 2

Core Principles & Definitions

Before we write any code, let's establish the key ideas behind array iteration and aggregation. An aggregate is a single value computed from many values — think of it as a summary statistic. The process of visiting each element in an array is called traversal, and we accomplish it by using loops. There are two main loop styles in Java for array traversal: the traditional for loop and the enhanced for-each loop.

1

Array Traversal

The process of visiting every element in an array exactly once, typically using a loop that starts at index 0 and ends at array.length − 1.
2

Accumulator Pattern

A variable initialized before the loop that gets updated with each iteration. For a sum, the accumulator starts at 0 and adds each element. For a product, it starts at 1 and multiplies.
3

Aggregate Functions

Common aggregates include sum, average, minimum, maximum, and count. Each uses the accumulator pattern with a different update rule inside the loop body.
4

Index vs. Value Access

A traditional for loop provides the index (position) and value. A for-each loop provides only the value. Choose based on whether you need the index for your computation.
5

Bounds Safety

Java throws an ArrayIndexOutOfBoundsException if you access an index outside 0 to length − 1. Always use < array.length (not <=) as your loop condition.
✦

KEY TAKEAWAY

Think of an array like a row of mailboxes in an apartment building. Each mailbox has a number (the index) and contains a letter (the value). Iteration is like a mail carrier walking from the first mailbox to the last, checking each one. An aggregate is the summary the carrier gives at the end — "there were 12 letters total" (sum) or "the heaviest package was 3 pounds" (max).

SECTION 3

Visual Explanation — How Array Iteration Works

The diagram below shows how a for loop traverses an integer array to compute a running sum. Notice how the index variable i advances from 0 to 4, and the accumulator variable sum grows as each element is added.

Array Traversal — Computing a Sumint[] scores = {10, 25, 8, 42, 15};Index:01234102584215Iteration Steps:Before loop:sum = 0i=0:sum = 0 + 10→sum = 10i=1:sum = 10 + 25→sum = 35i=2:sum = 35 + 8→sum = 43i=3:sum = 43 + 42→sum = 85i=4:sum = 85 + 15→sum = 100Final sum = 100
Each iteration reads one element from the array and adds it to the running sum accumulator. After all five elements are processed, the total is 100.

In the diagram above, each row represents one pass through the loop body. The index i moves from 0 to 4, and the accumulator sum grows by the value at that index. This is the accumulator pattern in action. Every aggregate — sum, count, min, max — uses a variation of this same idea: initialize a variable, loop through the array, and update the variable at each step.

SECTION 4

How It Works — Loop Structures & Code Patterns

The Traditional for Loop

The traditional for loop gives you full control over the index variable. Its structure has three parts separated by semicolons: initialization (run once before the loop starts), condition (checked before each iteration), and update (run after each iteration). The standard idiom for traversing an array looks like this:

TRADITIONAL FOR LOOP

for(inti=0;i<arr.length;i++)/∗usearr[i]∗/for (int i = 0; i < arr.length; i++) { /* use arr[i] */ }

i = index variable, starts at 0. arr.length = number of elements. arr[i] = element at position i.

The Enhanced for-each Loop

When you don't need the index — just the values — Java's enhanced for loop (also called the for-each loop) is cleaner. It automatically iterates through every element without requiring you to manage an index counter.

ENHANCED FOR-EACH LOOP

for(intvalue:arr)/∗usevalue∗/for (int value : arr) { /* use value */ }

value = a copy of each element in arr, visited in order from index 0 to length − 1.

Common Aggregate Patterns

SUM

intsum=0;for(intv:arr)sum+=v;int sum = 0; for (int v : arr) { sum += v; }

Accumulator starts at 0. Each element is added. After the loop, sum holds the total.

AVERAGE

doubleavg=(double)sum/arr.length;double avg = (double) sum / arr.length;

Compute the sum first, then divide by the number of elements. The cast to double avoids integer division truncation.

MIN / MAX

intmin=arr[0];for(intv:arr)if(v<min)min=v;int min = arr[0]; for (int v : arr) { if (v < min) min = v; }

Initialize to the first element (not to 0 or Integer.MAX_VALUE for beginners). Then compare each element and update if smaller. Replace < with > for maximum.

⚠

Why initialize min/max to arr[0]?

If you initialize min to 0 and all array values are positive, you'll get 0 as the minimum — which isn't even in the array! Starting with arr[0] guarantees your initial value is a real element, so comparisons work correctly for any set of values.

SECTION 5

Detailed Breakdown of Aggregate Operations

Each aggregate operation follows the same three-phase structure: initialize an accumulator variable, iterate through the array updating the accumulator, and report the result after the loop. What changes between different aggregates is the initialization value and the update rule. The diagram below summarizes the five most common aggregates side by side.

Five Common Aggregate OperationsSUMInit: sum = 0Update:sum += arr[i]Result: sumTotal of all valuesAVERAGEInit: sum = 0Update:sum += arr[i]Result:sum / lengthMINInit: min=arr[0]Update:if (v < min) min = vResult: minMAXInit: max=arr[0]Update:if (v > max) max = vResult: maxCOUNTInit: count = 0Update:if (condition) count++Result: countShared Three-Phase Pattern① INITIALIZESet accumulator value② ITERATELoop & update accum.③ REPORTUse/return resultExample with arr = {10, 25, 8, 42, 15}:Sum = 100Avg = 20.0Min = 8Max = 42Count(>10) = 3
All five aggregate operations follow the same three-phase pattern: Initialize → Iterate → Report. The only differences are the starting value and the update logic inside the loop.
AggregateInit ValueUpdate RuleResult Type
Sum0sum += arr[i]int or double
Average0 (sum first)sum += arr[i], then dividedouble
Minimumarr[0]if (arr[i] < min) min = arr[i]Same as array type
Maximumarr[0]if (arr[i] > max) max = arr[i]Same as array type
Count0if (condition) count++int

Summary of common aggregate operations

SECTION 6

Worked Example — Student Grade Analysis

Let's walk through a complete example that computes multiple aggregates from a single array. Suppose you have an array of test scores and you need to find the sum, average, highest score, lowest score, and how many students scored above 80.

Grade Analysis: Computing Five Aggregates

  1. 1

    Step 1 — Declare the Array

    Start by declaring and initializing the array of test scores: int[] grades = {72, 95, 88, 61, 84, 77, 93}; This creates an array with 7 elements at indices 0 through 6.
    Array length: grades.length = 7
  2. 2

    Step 2 — Initialize Accumulators

    We need five accumulator variables. For sum and count, we initialize to 0. For min and max, we initialize to the first element of the array: int sum = 0; int min = grades[0]; int max = grades[0]; int count = 0; Notice that we don't need a separate accumulator for average — we'll compute it from the sum after the loop.
    sum=0, min=72, max=72, count=0
  3. 3

    Step 3 — Write the Loop

    We can compute all aggregates in a single pass through the array using one for-each loop: for (int g : grades) { sum += g; if (g < min) min = g; if (g > max) max = g; if (g > 80) count++; } Each element is processed once, and all four accumulators are updated in the same loop body.
  4. 4

    Step 4 — Trace Through the Loop

    Let's trace iteration by iteration. After g=72: sum=72, min=72, max=72, count=0. After g=95: sum=167, min=72, max=95, count=1. After g=88: sum=255, min=72, max=95, count=2. After g=61: sum=316, min=61, max=95, count=2. After g=84: sum=400, min=61, max=95, count=3. After g=77: sum=477, min=61, max=95, count=3. After g=93: sum=570, min=61, max=95, count=4.
    sum=570, min=61, max=95, count=4
  5. 5

    Step 5 — Compute the Average

    After the loop, compute the average by casting the sum to double before dividing: double avg = (double) sum / grades.length; This gives us 570.0 ÷ 7 = 81.43 (rounded to two decimal places). Without the cast, Java would perform integer division and give us 81 instead of 81.43.
    Sum=570, Avg≈81.43, Min=61, Max=95, Above-80 Count=4
💡

Efficiency Tip

Notice that we computed all five aggregates in a single loop. You could write five separate loops — one for each aggregate — and get the same answers, but combining them into one loop means the array is only traversed once. This is both simpler to read and more efficient.

SECTION 7

Traditional for vs. Enhanced for-each

Both loop styles can accomplish array iteration, but they have different strengths. Choosing the right one depends on what your code needs to do. The table below breaks down the key differences.

FeatureTraditional for LoopEnhanced for-each Loop
Syntaxfor (int i = 0; i < arr.length; i++)for (int v : arr)
Index available?Yes — via iNo — only the value
Can modify elements?Yes — arr[i] = newValNo — v is a copy
Partial traversal?Yes — change start/end/stepNo — always visits every element
Risk of off-by-one?Yes — using <= instead of <No — loop manages bounds automatically
Best for aggregates?When you need the index (e.g., index of max)When you only need values (sum, avg, min, max)

Comparison of Java loop styles for array iteration

✦

KEY TAKEAWAY

Think of the traditional for loop like driving a car with a manual transmission — you have full control over every gear shift (index), but it requires more attention. The for-each loop is like an automatic transmission — simpler and less error-prone for the common case. For most aggregate computations, the for-each loop is the better choice because you just need the values, not the positions.

SECTION 8

Connection to Advanced Java Collections

The iteration and aggregation patterns you've learned here apply far beyond basic arrays. Java's Collections Framework provides dynamic data structures like ArrayList that grow and shrink as needed. The Stream API, introduced in Java 8, allows you to express aggregates in a more declarative style. Understanding the fundamental loop-based approach gives you the foundation to appreciate these more powerful tools later.

FeatureArray + Loop (This Lesson)ArrayList + Stream (Advanced)
SizeFixed at creation timeDynamic — grows automatically
Sumfor (int v : arr) sum += v;list.stream().mapToInt(x->x).sum()
MinManual loop with if-statementCollections.min(list)
Count with conditionLoop with if and counterlist.stream().filter(x->x>80).count()
When to learnNow — foundationalAfter mastering arrays and basic OOP

Arrays vs. Advanced Collections

Even though tools like Streams can compute aggregates in a single line, they work by doing the same iteration under the hood. Mastering the explicit loop-based approach ensures you understand exactly what the computer is doing at each step — which is critical for debugging, performance reasoning, and writing correct code in any language.

SECTION 9

Practice Problems

Question 1: CONCEPTUAL

Explain why we initialize the min variable to arr[0] instead of 0 when finding the minimum value in an array. Give a specific example where initializing to 0 would produce a wrong answer.
Show answer
If we initialize min to 0 and the array contains only positive numbers (for example, {5, 12, 3, 8}), the loop will never find a value less than 0. The result would be 0, which isn't even in the array. By initializing to arr[0], we guarantee the starting value is an actual array element. Every subsequent comparison then correctly checks whether another element is smaller than the current known minimum. This same reasoning applies to max — initializing to 0 could give wrong results if all values are negative.

Question 2: BASIC CALCULATION

Given int[] data = {14, 7, 23, 11, 19};, trace through a for-each loop to compute the sum. Show the value of sum after each iteration, and then calculate the average.
Show answer
We initialize sum = 0. After processing 14: sum = 14. After 7: sum = 21. After 23: sum = 44. After 11: sum = 55. After 19: sum = 74. The final sum is 74. To compute the average, we calculate (double) 74 / 5 = 14.8. The cast to double is essential — without it, Java would perform integer division and produce 14 instead of 14.8.

Question 3: INTERMEDIATE

Write a Java method called countAboveAverage that takes an int[] as a parameter and returns the number of elements that are strictly greater than the array's average. Hint: you will need two passes through the array.
Show answer
This problem requires two loops because you cannot compare elements to the average until you know the average. First loop: compute the sum, then calculate avg = (double) sum / arr.length. Second loop: count elements where arr[i] > avg. The code is: public static int countAboveAverage(int[] arr) { int sum = 0; for (int v : arr) sum += v; double avg = (double) sum / arr.length; int count = 0; for (int v : arr) if (v > avg) count++; return count; } For the array {14, 7, 23, 11, 19}, the average is 14.8, and the values above average are 23 and 19, so the method returns 2.

Question 4: APPLIED

A weather station records daily high temperatures (in °F) for a week: int[] temps = {68, 73, 81, 79, 85, 90, 72}; Write Java code that computes: (a) the average temperature, (b) the hottest day's temperature, (c) the index of the hottest day (0=Monday, 6=Sunday), and (d) how many days exceeded 80°F.
Show answer
For parts (a) and (d), a for-each loop works. For part (c), we need the index, so a traditional for loop is better. Here's a combined approach: int sum = 0, max = temps[0], maxIdx = 0, count = 0; for (int i = 0; i < temps.length; i++) { sum += temps[i]; if (temps[i] > max) { max = temps[i]; maxIdx = i; } if (temps[i] > 80) count++; } double avg = (double) sum / temps.length; Results: sum = 548, avg ≈ 78.29°F, max = 90 (at index 5, which is Saturday), and 3 days exceeded 80°F (81, 85, 90). Note that we needed the traditional for loop because part (c) asks for the index of the maximum, which the for-each loop cannot provide.

Question 5: CRITICAL THINKING

Consider an array that might be empty (length 0). Which aggregate operations would cause an error or produce a meaningless result if the array is empty? For each problematic aggregate, explain what goes wrong and propose a solution using a guard clause (an if-statement before the loop).
Show answer
Sum and count are safe on an empty array — they simply return their initial values (0). However, average, min, and max are problematic. For average, you'd divide by 0, which produces NaN for doubles or throws an ArithmeticException for integers. For min and max, initializing to arr[0] would throw an ArrayIndexOutOfBoundsException since there is no index 0. The solution is to add a guard clause at the top of your method: if (arr.length == 0) { /* return a default, throw an exception, or print an error */ } For example, you could return -1 or throw an IllegalArgumentException with a descriptive message. This pattern of checking for edge cases before processing is a critical habit in software development — it prevents crashes and produces more robust code.

SUMMARY

Lesson Summary

Summary

In this lesson, you learned how to traverse arrays using both the traditional for loop (which gives you index access) and the enhanced for-each loop (which simplifies value-only iteration). The core pattern behind all aggregate computations is the accumulator pattern: initialize a variable before the loop, update it inside the loop, and use it after the loop.

You applied this pattern to five common aggregates: sum (init to 0, add each element), average (sum divided by length, using a double cast), minimum and maximum (init to arr[0], compare with < or >), and conditional count (init to 0, increment when a condition is met). These patterns form the building blocks for data processing in every Java program you'll ever write, and they translate directly to more advanced tools like ArrayList and the Stream API.

Varsity Tutors • Java • Array Iteration & Aggregates