710 Stimmen

Finde das erste Element anhand eines Prädikats

Ich habe gerade angefangen, mit Java 8 Lambdas zu spielen und versuche, einige der Dinge zu implementieren, die ich von funktionalen Sprachen gewohnt bin.

Zum Beispiel haben die meisten funktionalen Sprachen eine Art find-Funktion, die auf Sequenzen oder Listen operiert und das erste Element zurückgibt, für das der Prädikat true ist. Der einzige Weg, den ich in Java 8 sehe, um das zu erreichen, ist:

lst.stream()
    .filter(x -> x > 5)
    .findFirst()

Dies scheint mir jedoch ineffizient zu sein, da der Filter die ganze Liste durchsucht, zumindest nach meinem Verständnis (das falsch sein könnte). Gibt es einen besseren Weg?

4voto

aillusions Punkte 164
import org.junit.Test;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

// Stream ist ~30 Mal langsamer für dieselbe Operation...
public class StreamPerfTest {

    int iterationen = 100;
    List liste = Arrays.asList(1, 10, 3, 7, 5);

    // 55 ms
    @Test
    public void stream() {

        for (int i = 0; i < iterationen; i++) {
            Optional ergebnis = liste.stream()
                    .filter(x -> x > 5)
                    .findFirst();

            System.out.println(ergebnis.orElse(null));
        }
    }

    // 2 ms
    @Test
    public void schleife() {

        for (int i = 0; i < iterationen; i++) {
            Integer ergebnis = null;
            for (Integer lauf : liste) {
                if (lauf > 5) {
                    ergebnis = lauf;
                    break;
                }
            }
            System.out.println(ergebnis);
        }
    }
}

1voto

lawrence-witt Punkte 8730

Ein generischer Hilfsfunktion mit Schleifen erscheint mir viel sauberer:

static public  T find(List elements, Predicate p) {
    for (T item : elements) if (p.test(item)) return item;
    return null;
}

static public  T find(T[] elements, Predicate p) {
    for (T item : elements) if (p.test(item)) return item;
    return null;
}

In Verwendung:

List intList = Arrays.asList(1, 2, 3, 4, 5);
Integer[] intArr = new Integer[]{1, 2, 3, 4, 5};

System.out.println(find(intList, i -> i % 2 == 0)); // 2
System.out.println(find(intArr, i -> i % 2 != 0)); // 1
System.out.println(find(intList, i -> i > 5)); // null

0voto

shreedhar bhat Punkte 4589

Verbesserte Einzeiler-Antwort: Wenn Sie nach einem booleschen Rückgabewert suchen, können wir es besser machen, indem wir isPresent hinzufügen:

return dataSource.getParkingLots().stream().filter(parkingLot -> Objects.equals(parkingLot.getId(), id)).findFirst().isPresent();

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X