Java Arena
Step 5 of 6

Linear search

The second problem of this module is searching: where in the array is a given value, if it's there at all? The simplest algorithm looks at the elements one at a time, from the first to the last, and stops at the first match. It's called linear search, since it goes through the elements in a line. You've written it before (module 15). Here it is as a method that returns the index of the value, or -1 when the value isn't there. -1 is never an index, so the caller can tell the two answers apart.

A raffle keeps the numbers of the tickets it has sold in an array:

public class Main {
    public static void main(String[] args) {
        int[] tickets = {512, 87, 340, 19, 777, 203};
        System.out.println(positionOf(tickets, 340));
        System.out.println(positionOf(tickets, 5));
    }

    public static int positionOf(int[] tickets, int wanted) {
        for (int i = 0; i < tickets.length; i++) {
            if (tickets[i] == wanted) {
                return i;
            }
        }
        return -1;
    }
}
Output
2
-1
  • return i; ends the method at the first match, loop and all. There's no need to look further.
  • return -1; comes after the loop. Only when every element has been looked at, and none matched, is it clear that the value isn't there.
  • The array doesn't need to be in any order. Linear search works on any array or list.

How much work is it?

Count the values the search looks at. Each look is one comparison, tickets[i] == wanted. Finding 340 at index 2 took 3 looks, at indexes 0, 1 and 2. A value at index i takes i + 1 looks. A value that isn't there takes a look at every element, since the search can't stop early.

Array size Values looked at, at most
6 6
1,000 1,000
1,000,000 1,000,000

The work grows in step with the array: twice the values, twice the looks at worst. A value that is there is found, on average, about halfway through. That's fine for most programs, but one that searches a million values over and over has a lot to do. The next step shows how sorted data makes searching much faster.

The list methods indexOf and contains (module 14) do a linear search for you: they go through the list from the start, and compare each element with the value using equals.

Searching a list of objects

Often the values are objects, and the search compares one of their instance variables. Here a music library finds an album by its title:

Main.java
import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<Album> albums = new ArrayList<>();
        albums.add(new Album("Kind of Blue", 1959));
        albums.add(new Album("Abbey Road", 1969));
        albums.add(new Album("Rumours", 1977));

        int index = indexOfTitle(albums, "Abbey Road");
        System.out.println(index + ": " + albums.get(index));
        System.out.println(indexOfTitle(albums, "Thriller"));
    }

    public static int indexOfTitle(ArrayList<Album> albums, String title) {
        for (int i = 0; i < albums.size(); i++) {
            if (albums.get(i).getTitle().equals(title)) {
                return i;
            }
        }
        return -1;
    }
}
Album.java
public class Album {
    private String title;
    private int year;

    public Album(String title, int year) {
        this.title = title;
        this.year = year;
    }

    public String getTitle() {
        return this.title;
    }

    public int getYear() {
        return this.year;
    }

    public String toString() {
        return this.title + " (" + this.year + ")";
    }
}
Output
1: Abbey Road (1969)
-1
  • The loop goes over the indexes, so that it has an index to return. albums.get(i) is the album at index i, and getTitle() gives its title.
  • Titles are Strings, so they're compared with equals, not == (module 16).
  • albums.indexOf can't do this search: it would need an Album object equal to the one on the list, and all the program has is a title.

Your task

Challenge 1 of 3

In a small harbor, each berth holds one boat, and the array berths holds the boats' registration numbers, one per berth. Write the method berthOf(int[] berths, int boat), which returns the index of the berth where the boat is, or -1 if it isn't in the harbor. The check runs:

int[] berths = {305, 118, 442, 97};
System.out.println(berthOf(berths, 442));
System.out.println(berthOf(berths, 500));

and expects:

2
-1

Challenge 2

This search has a common mistake in it. What does the program print?

Challenge 3

Departure.java is ready: a bus departure has a line, such as "14", and a time, such as "08:05", with the getters getLine() and getTime(). The departures are in a list, in time order. In Main.java, write the method firstOnLine(ArrayList<Departure> departures, String line), which returns the index of the first departure of the given line, or -1 if no bus of that line leaves. The check runs:

ArrayList<Departure> departures = new ArrayList<>();
departures.add(new Departure("14", "08:05"));
departures.add(new Departure("3", "08:12"));
departures.add(new Departure("22", "08:20"));
departures.add(new Departure("3", "08:31"));
System.out.println(firstOnLine(departures, "3"));
System.out.println(firstOnLine(departures, "7"));

and expects:

1
-1