Wie lässt sich prüfen, ob ein bestimmter Inhalt in einem Array enthalten ist?

Das Durchlaufen eines Arrays in einer Schleife, um auf einen bestimmten Inhalt zu prüfen, erscheint auf den ersten Blick umständlich und gefühlt wenig effizient. Ist es das tatsächlich?

Um zu prüfen, ob ein bestimmter Inhalt in einem Array gespeichert ist, werden vier Verfahren hinsichtlich ihrer Geschwindigkeit unter gängigen Anwendungsbedingungen1 verglichen:

Für jedes Verfahren wird eine eigene Methode verwendet, die natürlich gesondert aufgerufen wird. Ihre Einbettung findet dann an der Stelle des Kommentars "// Methodenaufruf" statt:

public class Arraysuche {

    public static void main(String[] args) {
        final int runs = 10000;
        final int size = 1000000;
        Integer search = new Integer(987654);
        Integer[] iArr = new Integer[size];

        for (int i = 0; i < iArr.length; ++i) {
            iArr[i] = new Integer(i);
        }
        long count = 0;
        long timeStart = 0;
        long timeEnd = 0;
        for (int i = 0; i < runs; ++i) {
            timeStart = System.nanoTime();
            timeEnd = 0;
            if (
                   // Methodenaufruf
               ) {
                timeEnd = System.nanoTime();
                count += (timeEnd - timeStart);
                iArr = null;
                search = null;
                System.gc();
                break;
            }
        }
        System.out.println("Laufzeitdurchschnitt: " + (count / runs));
    }
    //..
}

Das Grundprinzip besteht darin, dass vor dem Start und nach Abschluss jedes Suchdurchlaufs die Zeit genommen wird, deren Differenz dann die Dauer eines Suchlaufs ergibt. In einer Schleife wird darüber hinaus jeder Suchlauf 10.000 Mal wiederholt und von diesen Zeiten der Mittelwert errechnet.
Die Ergebnisse jeweils dreier Ausführungen sind unter den Methoden in Nanosekunden notiert:

private static boolean checkLoop(Integer[] arr, Integer search) {
        for (int i = 0; i < arr.length; ++i) {
            if (arr[i].equals(search)) {
                return true;
            }
        }
        return false;
    }
    
    // 1147
    // 1702
    // 1165
private static boolean checkList(Integer[] arr, Integer search) {
        if (Arrays.asList(arr).contains(search)) {
            return true;
        }
        return false;
    }
    
    // 1358
    // 1612
    // 1327
private static boolean checkBinarySearch(Integer[] arr, Integer search) {
        if (Arrays.binarySearch(arr, search) >= 0) {
            return true;
        }
        return false;
    }
    
    // 4
    // 4
    // 4
private static boolean checkStream(Integer[] arr, Integer search) {
        if (Arrays.stream(arr).anyMatch(s -> s.equals(search))) {
            return true;
        }
        return false;
    }
    
    // 14684
    // 14608
    // 14548

Die Ergebnisse sprechen für sich: Die binäre Suche stellt das mit Abstand schnellste Verfahren dar, während der Stream etwa um das Zehnfache langsamer ist, als die beiden etwa gleichauf liegenden Verfahren des Schleifendurchlauf-Vergleichs und der Wandlung in die ArrayList.

1) MacBook Pro 14", Apple M1 Pro, 16GB, MacOS Monterey