2717 Stimmen

Wie kann ich in Java feststellen, ob ein Array einen bestimmten Wert enthält?

Ich habe eine String[] mit Werten wie diesen:

public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};

Gegeben String s Gibt es eine gute Methode, um zu testen, ob VALUES enthält s ?

6 Stimmen

Das ist ein langer Weg, aber Sie können eine for-Schleife verwenden: "for (String s : VALUES) if (s.equals("MYVALUE")) return true;

1 Stimmen

Ja, es war mir fast peinlich, die Frage zu stellen, aber gleichzeitig war ich überrascht, dass sie noch nicht gestellt worden war. Es ist eine dieser APIs, mit denen ich einfach noch nicht in Berührung gekommen bin...

3 Stimmen

@camickr - ich habe eine fast identische Situation mit diesem hier: stackoverflow.com/a/223929/12943 Es wird immer wieder abgestimmt, obwohl es nur ein Copy/Paste aus der Sun-Dokumentation war. Ich schätze, die Bewertung basiert darauf, wie viel Hilfe man geleistet hat und nicht darauf, wie viel Mühe man sich gegeben hat - und vor allem darauf, wie schnell man es veröffentlicht hat! Vielleicht sind wir auf das Geheimnis von John Skeet gestoßen! Nun, gute Antwort, +1 für Sie.

76voto

Uri Punkte 86472

Wenn das Array nicht sortiert ist, müssen Sie alles durchgehen und für jedes Element einen Aufruf von equals durchführen.

Wenn das Array sortiert ist, können Sie eine binäre Suche durchführen, es gibt eine in der Arrays Klasse.

Im Allgemeinen sollten Sie, wenn Sie viele Mitgliedschaftsprüfungen durchführen wollen, alles in einem Set und nicht in einem Array speichern.

1 Stimmen

Außerdem, wie ich in meiner Antwort sagte, wenn Sie die Arrays-Klasse verwenden, können Sie das Array sortieren und dann die binäre Suche auf dem neu sortierten Array durchführen.

1 Stimmen

@Thomas: Ich stimme zu. Oder Sie können einfach alles in ein TreeSet hinzufügen; gleiche Komplexität. Ich würde die Arrays verwenden, wenn es sich nicht ändert (vielleicht ein wenig Speicherplatz sparen, da die Referenzen zusammenhängend sind, obwohl die Strings nicht sind). Ich würde die Menge verwenden, wenn dies im Laufe der Zeit ändern würde.

54voto

camickr Punkte 315810

Ich habe einen Test durchgeführt, in dem ich die 3 Vorschläge in Bezug auf die Geschwindigkeit verglichen habe. Ich generierte zufällige Ganzzahlen, konvertierte sie in einen String und fügte sie zu einem Array hinzu. Dann suchte ich nach der höchstmöglichen Zahl/Zeichenkette, die im schlimmsten Fall für die asList().contains() .

Bei einer Array-Größe von 10K waren die Ergebnisse wie folgt:

Sort & Search   : 15
Binary Search   : 0
asList.contains : 0

Bei Verwendung eines 100K-Arrays waren die Ergebnisse wie folgt:

Sort & Search   : 156
Binary Search   : 0
asList.contains : 32

Wenn also das Array in sortierter Reihenfolge erstellt wird, ist die binäre Suche die schnellste, andernfalls die asList().contains wäre der richtige Weg. Wenn Sie viele Suchanfragen haben, kann es sich lohnen, das Array zu sortieren, damit Sie die binäre Suche verwenden können. Es hängt alles von Ihrer Anwendung ab.

Ich denke, das sind die Ergebnisse, die die meisten Menschen erwarten würden. Hier ist der Testcode:

import java.util.*;

public class Test {
    public static void main(String args[]) {
        long start = 0;
        int size = 100000;
        String[] strings = new String[size];
        Random random = new Random();

        for (int i = 0; i < size; i++)
            strings[i] = "" + random.nextInt(size);

        start = System.currentTimeMillis();
        Arrays.sort(strings);
        System.out.println(Arrays.binarySearch(strings, "" + (size - 1)));
        System.out.println("Sort & Search : "
                + (System.currentTimeMillis() - start));

        start = System.currentTimeMillis();
        System.out.println(Arrays.binarySearch(strings, "" + (size - 1)));
        System.out.println("Search        : "
                + (System.currentTimeMillis() - start));

        start = System.currentTimeMillis();
        System.out.println(Arrays.asList(strings).contains("" + (size - 1)));
        System.out.println("Contains      : "
                + (System.currentTimeMillis() - start));
    }
}

6 Stimmen

Ich verstehe diesen Code nicht. Sie sortieren das Array 'strings' und verwenden das gleiche (sortierte) Array in beiden Aufrufen von binarySearch. Wie kann das etwas anderes als eine HotSpot-Laufzeitoptimierung darstellen? Dasselbe gilt für den Aufruf von asList.contains. Sie erstellen eine Liste aus dem sortierten Array und führen dann contains mit dem höchsten Wert darauf aus. Das dauert natürlich seine Zeit. Was ist der Sinn dieses Tests? Ganz zu schweigen davon, dass es sich um einen unsachgemäß geschriebenen Microbenchmark handelt.

0 Stimmen

Da die binäre Suche nur auf eine sortierte Menge angewendet werden kann, ist Sortieren und Suchen die einzige Möglichkeit, die binäre Suche zu verwenden.

1 Stimmen

Die Sortierung kann aus einer Reihe anderer Gründe bereits erfolgt sein, z. B. könnte die Sortierung bei der Installation vorgenommen und nie geändert worden sein. Es ist sinnvoll, die Suchzeit an sich zu testen. Der Nachteil ist jedoch, dass es sich hierbei um ein weniger gutes Beispiel für Microbenchmarking handelt. Mikrobenchmarks sind in Java bekanntermaßen schwer zu bewerkstelligen und sollten beispielsweise die Ausführung des Testcodes in ausreichendem Maße beinhalten, um eine Hotspot-Optimierung zu erhalten, bevor der eigentliche Test ausgeführt wird, ganz zu schweigen davon, dass der eigentliche Testcode mehr als EINMAL mit einem Timer ausgeführt wird. Beispielhafte Fallstricke

42voto

Mark Rhodes Punkte 9675

Anstatt die schnelle Array-Initialisierungssyntax zu verwenden, könnten Sie sie auch gleich als Liste in ähnlicher Weise mit der Methode Arrays.asList initialisieren, z. B.:

public static final List<String> STRINGS = Arrays.asList("firstString", "secondString" ...., "lastString");

Dann können Sie (wie oben) vorgehen:

STRINGS.contains("the string you want to find");

40voto

assylias Punkte 308529

Mit Java 8 können Sie einen Stream erstellen und prüfen, ob die Einträge im Stream "s" :

String[] values = {"AB","BC","CD","AE"};
boolean sInArray = Arrays.stream(values).anyMatch("s"::equals);

Oder als generische Methode:

public static <T> boolean arrayContains(T[] array, T value) {
    return Arrays.stream(array).anyMatch(value::equals);
}

4 Stimmen

Es lohnt sich auch, die primitiven Spezialisierungen zu beachten.

0 Stimmen

Auch hinzuzufügen, anyMatch JavaDoc besagt, dass es "...May not evaluate the predicate on all elements if not necessary for determining the result." so dass die Verarbeitung nach dem Finden einer Übereinstimmung möglicherweise nicht fortgesetzt werden muss.

29voto

Thomas Owens Punkte 110966

Sie können die Arrays-Klasse um eine binäre Suche nach dem Wert durchzuführen. Wenn Ihr Array nicht sortiert ist, müssen Sie die Sortierfunktionen in derselben Klasse verwenden, um das Array zu sortieren und es dann zu durchsuchen.

0 Stimmen

Sie können die Sortierfunktionen in der gleichen Klasse verwenden, um das zu erreichen... Ich sollte das zu meiner Antwort hinzufügen.

1 Stimmen

Wird wahrscheinlich mehr kosten als die asList().contains() Ansatz, dann, ich denke. Es sei denn, Sie müssen diese Überprüfung sehr oft tun (aber wenn es nur eine statische Liste von Werten ist, die sortiert werden kann, um mit zu beginnen, um fair zu sein).

0 Stimmen

Wahr. Es gibt viele Variablen, um zu entscheiden, was am effektivsten wäre. Aber es ist gut, Optionen zu haben.

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