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
?
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
?
Arrays.asList(yourArray).contains(yourValue)
Achtung: Dies funktioniert nicht für Arrays von Primitiven (siehe Kommentare).
String[] values = {"AB","BC","CD","AE"};
boolean contains = Arrays.stream(values).anyMatch("s"::equals);
Um zu prüfen, ob ein Array von int
, double
o long
enthält einen Wert Verwendung IntStream
, DoubleStream
o LongStream
beziehungsweise.
int[] a = {1,2,3,4};
boolean contains = IntStream.of(a).anyMatch(x -> x == 4);
Ich bin etwas neugierig auf die Leistung dieser im Vergleich zu den Suchfunktionen in der Klasse Arrays versus Iteration über ein Array und mit einem equals() Funktion oder == für Primitive.
@Thomas: Ich denke, dass asList() tatsächlich ein neues Objekt zuweisen könnte, das an das vorhandene Array delegiert, so dass Sie die Zuweisungskosten bezahlen. Die Liste wird durch das Array unterstützt, so dass die Elemente selbst nicht neu zugewiesen werden sollten.
Referenz-Arrays sind schlecht. In diesem Fall suchen wir eine Menge. Seit Java SE 9 haben wir Set.of
.
private static final Set<String> VALUES = Set.of(
"AB","BC","CD","AE"
);
"Gibt es bei einer Zeichenkette s eine gute Möglichkeit zu prüfen, ob VALUES s enthält?"
VALUES.contains(s)
O(1).
Le site richtige Art , unveränderlich , O(1) y kurz und bündig . Schön.*
Nur um den Code zunächst einmal zu klären. Wir haben (korrigiert):
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Dies ist ein veränderbares statisches Element, das FindBugs als sehr unanständig bezeichnen wird. Ändern Sie keine Statics und erlauben Sie anderen Code nicht, dies ebenfalls zu tun. Als absolutes Minimum sollte das Feld privat sein:
private static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
(Hinweis: Sie können die new String[];
bit.)
Referenz-Arrays sind immer noch schlecht, und wir wollen einen Satz:
private static final Set<String> VALUES = new HashSet<String>(Arrays.asList(
new String[] {"AB","BC","CD","AE"}
));
(Paranoide Menschen, wie ich selbst, würden sich vielleicht wohler fühlen, wenn dies in Collections.unmodifiableSet
- sie könnte dann sogar veröffentlicht werden).
(*Um ein wenig mehr auf der Höhe der Zeit zu sein, die Sammlungen API ist vorhersehbar immer noch fehlen unveränderliche Sammlungstypen und die Syntax ist immer noch viel zu langatmig, für meinen Geschmack).
Wenn sie statisch ist, wird sie wahrscheinlich ziemlich oft benutzt werden. Der Zeitaufwand für die Initialisierung der Menge ist also im Vergleich zu den Kosten für eine Vielzahl von linearen Suchvorgängen sehr gering.
Die Erstellung der Sammlung wird dann von der Ladezeit des Codes dominiert (die technisch gesehen O(n) ist, aber praktisch konstant).
Sie können verwenden ArrayUtils.contains
de Apache Commons Lang
public static boolean contains(Object[] array, Object objectToFind)
Beachten Sie, dass diese Methode Folgendes zurückgibt false
wenn das übergebene Array null
.
Es gibt auch Methoden für primitive Arrays aller Art.
String[] fieldsToInclude = { "id", "name", "location" };
if ( ArrayUtils.contains( fieldsToInclude, "id" ) ) {
// Do some stuff.
}
@max4ever Ich stimme zu, aber das ist immer noch besser als "Rolling your own" und einfacher zu lesen als der rohe Java-Weg.
@max4ever Manchmal haben Sie diese Bibliothek bereits integriert (aus anderen Gründen) und es ist eine vollkommen gültige Antwort. Ich habe danach gesucht und bin bereits auf Apache Commons Lang angewiesen. Vielen Dank für diese Antwort.
Führen Sie es einfach von Hand aus:
public static <T> boolean contains(final T[] array, final T v) {
for (final T e : array)
if (e == v || v != null && v.equals(e))
return true;
return false;
}
Verbesserung:
Le site v != null
Bedingung innerhalb der Methode konstant ist. Sie wird während des Methodenaufrufs immer auf denselben booleschen Wert ausgewertet. Wenn also die Eingabe array
groß ist, ist es effizienter, diese Bedingung nur einmal auszuwerten, und wir können eine vereinfachte/schnellere Bedingung innerhalb der for
Schleife auf der Grundlage des Ergebnisses. Die verbesserte contains()
Methode:
public static <T> boolean contains2(final T[] array, final T v) {
if (v == null) {
for (final T e : array)
if (e == null)
return true;
}
else {
for (final T e : array)
if (e == v || v.equals(e))
return true;
}
return false;
}
Wie groß wäre der Leistungsunterschied zwischen dieser Lösung und der akzeptierten Antwort?
@Phoexo Diese Lösung ist offensichtlich schneller, weil die akzeptierte Antwort das Array in eine Liste umwandelt und die Methode contains() für diese Liste aufruft, während meine Lösung im Grunde das tut, was contains() nur tun würde.
E == v || v != null && v.equals( e ) --- Der erste Teil der OR-Anweisung vergleicht e und v. Der zweite Teil tut dasselbe (nachdem er überprüft hat, dass v nicht null ist). Warum sollte man eine solche Implementierung haben, anstatt nur (e==v). Können Sie mir das erklären?
Vier verschiedene Möglichkeiten zu prüfen, ob ein Array einen Wert enthält
Verwendung von List
:
public static boolean useList(String[] arr, String targetValue) {
return Arrays.asList(arr).contains(targetValue);
}
Verwendung von Set
:
public static boolean useSet(String[] arr, String targetValue) {
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
}
Verwendung einer einfachen Schleife:
public static boolean useLoop(String[] arr, String targetValue) {
for (String s: arr) {
if (s.equals(targetValue))
return true;
}
return false;
}
Verwendung von Arrays.binarySearch()
:
Der unten stehende Code ist falsch, er wird hier nur der Vollständigkeit halber aufgeführt. binarySearch()
kann NUR für sortierte Arrays verwendet werden. Das Ergebnis finden Sie weiter unten. Dies ist die beste Option, wenn das Feld sortiert ist.
public static boolean binarySearch(String[] arr, String targetValue) {
return Arrays.binarySearch(arr, targetValue) >= 0;
}
String testValue="test";
String newValueNotInList="newValue";
String[] valueArray = { "this", "is", "java" , "test" };
Arrays.asList(valueArray).contains(testValue); // returns true
Arrays.asList(valueArray).contains(newValueNotInList); // returns false
Und warum? Ich denke, es sollte ein > -1 zurückgeben, da 0 anzeigen würde, dass es am Kopf des Arrays enthalten ist.
Die erste Variante mit (a >= 0)
richtig war, überprüfen Sie einfach die Dokumente Sie sagen: "Beachten Sie, dass dies garantiert, dass der Rückgabewert >= 0 ist, wenn und nur wenn der Schlüssel gefunden wird".
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.
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.
3 Stimmen
Wenn Sie Apache Commons verwenden, dann org.apache.commons.lang.ArrayUtils.contains() tut dies für Sie.
0 Stimmen
@Zach: Sie tappen in die Falle des for-if-Antipatterns, tun Sie das nicht.
50 Stimmen
@camickr weil Leute, wie ich, eine Frage googeln, auf das SO-Ergebnis klicken, Ihre Antwort sehen, sie testen, es funktioniert, die Antwort hoch bewerten und dann gehen.
2 Stimmen
Ich vermisse wirklich eine einfache
indexOf
etcontains
injava.util.Arrays
- die beide unkomplizierte Schleifen enthalten würden. Ja, Sie können diese in 1 Minute schreiben; aber ich ging trotzdem zu StackOverflow in der Erwartung, sie irgendwo im JDK zu finden.