Ich habe einen String[]
mit Werten wie diesen:
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Gibt String s
es eine gute Möglichkeit zu testen, ob es VALUES
enthält s
?
Ich habe einen String[]
mit Werten wie diesen:
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Gibt String s
es eine gute Möglichkeit zu testen, ob es VALUES
enthält s
?
Antworten:
Arrays.asList(yourArray).contains(yourValue)
Warnung: Dies funktioniert nicht für Arrays von Grundelementen (siehe Kommentare).
String[] values = {"AB","BC","CD","AE"};
boolean contains = Arrays.stream(values).anyMatch("s"::equals);
Um zu überprüfen , ob eine Reihe von int
, double
oder long
einen Wert enthält , Verwendung IntStream
, DoubleStream
oder LongStream
jeweils.
int[] a = {1,2,3,4};
boolean contains = IntStream.of(a).anyMatch(x -> x == 4);
ArrayList
, aber nicht java.util.ArrayList
wie erwartet, die zurückgegebene reale Klasse ist: java.util.Arrays.ArrayList<E>
definiert als : public class java.util.Arrays {private static class ArrayList<E> ... {}}
.
Referenzarrays sind schlecht. Für diesen Fall sind wir nach einem Satz. Seit Java SE 9 haben wir Set.of
.
private static final Set<String> VALUES = Set.of(
"AB","BC","CD","AE"
);
"Gibt es bei String s eine gute Möglichkeit zu testen, ob VALUES s enthält?"
VALUES.contains(s)
O (1).
Der richtige Typ , unveränderlich , O (1) und prägnant . Wunderschönen.*
Nur um den Code zu löschen. Wir haben (korrigiert):
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Dies ist eine veränderbare statische Aufladung, von der FindBugs sagt, dass sie sehr ungezogen ist. Ändern Sie die Statik nicht und lassen Sie dies auch nicht von anderem Code zu. Das Feld sollte mindestens privat sein:
private static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
(Beachten Sie, dass Sie das new String[];
Bit tatsächlich löschen können .)
Referenz-Arrays sind immer noch schlecht und wir wollen eine Menge:
private static final Set<String> VALUES = new HashSet<String>(Arrays.asList(
new String[] {"AB","BC","CD","AE"}
));
(Paranoide Menschen wie ich fühlen sich möglicherweise wohler, wenn dies eingewickelt wird Collections.unmodifiableSet
- es könnte dann sogar veröffentlicht werden.)
(* Um ein bisschen mehr über die Marke zu erfahren, fehlen in der Sammlungs-API voraussichtlich immer noch unveränderliche Sammlungstypen, und die Syntax ist für meinen Geschmack immer noch viel zu ausführlich.)
Arrays.asList
)?
TreeSet
wäre O(log n)
. HashSet
s sind so skaliert, dass die mittlere Anzahl von Elementen in einem Bucket ungefähr konstant ist. Zumindest für Arrays bis 2 ^ 30. Es kann beispielsweise Auswirkungen von Hardware-Caches geben, die von der Big-O-Analyse ignoriert werden. Nimmt auch an, dass die Hash-Funktion effektiv funktioniert.
Sie können ArrayUtils.contains
von Apache Commons Lang verwenden
public static boolean contains(Object[] array, Object objectToFind)
Beachten Sie, dass diese Methode zurückgegeben wird, false
wenn das übergebene Array ist null
.
Es gibt auch Methoden für primitive Arrays aller Art.
String[] fieldsToInclude = { "id", "name", "location" };
if ( ArrayUtils.contains( fieldsToInclude, "id" ) ) {
// Do some stuff.
}
Einfach von Hand umsetzen:
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:
Die v != null
Bedingung ist innerhalb der Methode konstant. Während des Methodenaufrufs wird immer der gleiche Boolesche Wert ausgewertet. Wenn die Eingabe array
also groß ist, ist es effizienter, diese Bedingung nur einmal auszuwerten, und wir können eine vereinfachte / schnellere Bedingung innerhalb der for
Schleife basierend auf dem Ergebnis verwenden. 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;
}
Collection.contains(Object)
Arrays
und ArrayList
sich herausstellt, dass dies nicht unbedingt schneller ist als die verwendete Version Arrays.asList(...).contains(...)
. Der Aufwand für das Erstellen eines ArrayList
ist extrem gering und ArrayList.contains()
verwendet eine intelligentere Schleife (tatsächlich werden zwei verschiedene Schleifen verwendet) als die oben gezeigte (JDK 7).
Vier verschiedene Möglichkeiten, um zu überprüfen, ob ein Array einen Wert enthält
1) Verwenden der Liste:
public static boolean useList(String[] arr, String targetValue) {
return Arrays.asList(arr).contains(targetValue);
}
2) Verwenden von Set:
public static boolean useSet(String[] arr, String targetValue) {
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
}
3) Verwenden einer einfachen Schleife:
public static boolean useLoop(String[] arr, String targetValue) {
for (String s: arr) {
if (s.equals(targetValue))
return true;
}
return false;
}
4) Verwenden von Arrays.binarySearch ():
Der folgende Code ist falsch, der Vollständigkeit halber hier aufgeführt. binarySearch () kann NUR für sortierte Arrays verwendet werden. Sie werden feststellen, dass das Ergebnis unten seltsam ist. Dies ist die beste Option, wenn das Array sortiert ist.
public static boolean binarySearch(String[] arr, String targetValue) {
int a = Arrays.binarySearch(arr, targetValue);
return a > 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
(a >= 0)
war korrekt. Überprüfen Sie einfach die Dokumente . Sie sagen: "Beachten Sie, dass dies garantiert, dass der Rückgabewert genau dann> = 0 ist, wenn der Schlüssel gefunden wird."
Wenn das Array nicht sortiert ist, müssen Sie alles durchlaufen und bei jedem 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.
Wenn Sie viele Mitgliedschaftsprüfungen durchführen möchten, möchten Sie im Allgemeinen möglicherweise alles in einem Set und nicht in einem Array speichern.
Für das, was es wert ist, habe ich einen Test durchgeführt, bei dem die 3 Vorschläge für die Geschwindigkeit verglichen wurden. Ich habe zufällige Ganzzahlen generiert, sie in einen String konvertiert und einem Array hinzugefügt. Ich suchte dann nach der höchstmöglichen Zahl / Zeichenfolge, was ein Worst-Case-Szenario für die wäre asList().contains()
.
Bei Verwendung einer 10K-Arraygröße waren die Ergebnisse:
Sortieren & Suchen: 15 Binäre Suche: 0 asList.contains: 0
Bei Verwendung eines 100K-Arrays waren die Ergebnisse:
Sortieren & Suchen: 156 Binäre Suche: 0 asList.contains: 32
Wenn das Array also in sortierter Reihenfolge erstellt wird, ist die binäre Suche am schnellsten, andernfalls asList().contains
wäre dies der richtige Weg. Wenn Sie viele Suchvorgänge haben, kann es sinnvoll sein, das Array zu sortieren, damit Sie die binäre Suche verwenden können. Es hängt alles von Ihrer Anwendung ab.
Ich würde denken, das sind die Ergebnisse, die die meisten Leute 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));
}
}
Anstatt auch die Syntax für die schnelle Array-Initialisierung zu verwenden, können Sie sie auf ähnliche Weise sofort mit der Methode Arrays.asList als Liste initialisieren, z.
public static final List<String> STRINGS = Arrays.asList("firstString", "secondString" ...., "lastString");
Dann können Sie (wie oben) tun:
STRINGS.contains("the string you want to find");
Mit Java 8 können Sie einen Stream erstellen und prüfen, ob Einträge im Stream übereinstimmen "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);
}
anyMatch
JavaDoc an, dass dies der Fall ist "...May not evaluate the predicate on all elements if not necessary for determining the result."
, sodass die Verarbeitung nach dem Finden einer Übereinstimmung möglicherweise nicht fortgesetzt werden muss.
Mit der Arrays-Klasse können Sie eine binäre Suche nach dem Wert durchführen. Wenn Ihr Array nicht sortiert ist, müssen Sie die Sortierfunktionen in derselben Klasse verwenden, um das Array zu sortieren, und es dann durchsuchen.
ObStupidAnswer (aber ich denke, hier gibt es irgendwo eine Lektion):
enum Values {
AB, BC, CD, AE
}
try {
Values.valueOf(s);
return true;
} catch (IllegalArgumentException exc) {
return false;
}
Wenn Sie HashSet <String> verwenden, wie von Tom Hawtin vorgeschlagen, müssen Sie sich keine Gedanken über das Sortieren machen, und Ihre Geschwindigkeit ist dieselbe wie bei der binären Suche in einem vorsortierten Array, wahrscheinlich sogar noch schneller.
Es hängt natürlich alles davon ab, wie Ihr Code eingerichtet ist, aber von meinem Standpunkt aus wäre die Reihenfolge:
Auf einem unsortierten Array:
Auf einem sortierten Array:
Also so oder so, HashSet für den Sieg.
Wenn Sie über die Google-Sammlungsbibliothek verfügen, kann Toms Antwort mithilfe von ImmutableSet (http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/ImmutableSet.html) erheblich vereinfacht werden.
Dies beseitigt wirklich viel Unordnung bei der vorgeschlagenen Initialisierung
private static final Set<String> VALUES = ImmutableSet.of("AB","BC","CD","AE");
Eine mögliche Lösung:
import java.util.Arrays;
import java.util.List;
public class ArrayContainsElement {
public static final List<String> VALUES = Arrays.asList("AB", "BC", "CD", "AE");
public static void main(String args[]) {
if (VALUES.contains("AB")) {
System.out.println("Contains");
} else {
System.out.println("Not contains");
}
}
}
Entwickler tun oft:
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
Der obige Code funktioniert, es ist jedoch nicht erforderlich, eine Liste zu konvertieren, um sie zuerst festzulegen. Das Konvertieren einer Liste in einen Satz erfordert zusätzliche Zeit. Es kann so einfach sein wie:
Arrays.asList(arr).contains(targetValue);
oder
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;
Der erste ist besser lesbar als der zweite.
Die Verwendung einer einfachen Schleife ist der effizienteste Weg, dies zu tun.
boolean useLoop(String[] arr, String targetValue) {
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;
}
Mit freundlicher Genehmigung von Programcreek
Verwenden Sie in Java 8 Streams.
List<String> myList =
Arrays.asList("a1", "a2", "b1", "c2", "c1");
myList
.stream()
.filter(s -> s.startsWith("c"))
.map(String::toUpperCase)
.sorted()
.forEach(System.out::println);
Verwenden Sie für Arrays mit begrenzter Länge Folgendes (wie von camickr angegeben ). Dies ist bei wiederholten Überprüfungen langsam, insbesondere bei längeren Arrays (lineare Suche).
Arrays.asList(...).contains(...)
Für eine schnelle Leistung, wenn Sie wiederholt mit einem größeren Satz von Elementen vergleichen
Ein Array ist die falsche Struktur. Verwenden Sie a TreeSet
und fügen Sie jedes Element hinzu. Es sortiert Elemente und hat eine schnelle exist()
Methode (binäre Suche).
Wenn die Elemente implementiert werden Comparable
und Sie möchten, dass die entsprechend TreeSet
sortiert werden:
ElementClass.compareTo()
Methode muss kompatibel sein mit ElementClass.equals()
: Siehe Triaden, die nicht zum Kampf erscheinen? (Java Set fehlt ein Element)
TreeSet myElements = new TreeSet();
// Do this for each element (implementing *Comparable*)
myElements.add(nextElement);
// *Alternatively*, if an array is forceably provided from other code:
myElements.addAll(Arrays.asList(myArray));
Verwenden Sie andernfalls Ihre eigenen Comparator
:
class MyComparator implements Comparator<ElementClass> {
int compareTo(ElementClass element1; ElementClass element2) {
// Your comparison of elements
// Should be consistent with object equality
}
boolean equals(Object otherComparator) {
// Your equality of comparators
}
}
// construct TreeSet with the comparator
TreeSet myElements = new TreeSet(new MyComparator());
// Do this for each element (implementing *Comparable*)
myElements.add(nextElement);
Die Auszahlung: Überprüfen Sie die Existenz eines Elements:
// Fast binary search through sorted elements (performance ~ log(size)):
boolean containsElement = myElements.exists(someElement);
TreeSet
? HashSet
ist schneller (O (1)) und erfordert keine Bestellung.
Versuche dies:
ArrayList<Integer> arrlist = new ArrayList<Integer>(8);
// use add() method to add elements in the list
arrlist.add(20);
arrlist.add(25);
arrlist.add(10);
arrlist.add(15);
boolean retval = arrlist.contains(10);
if (retval == true) {
System.out.println("10 is contained in the list");
}
else {
System.out.println("10 is not contained in the list");
}
Verwenden Sie Folgendes (die contains()
Methode befindet sich ArrayUtils.in()
in diesem Code):
ObjectUtils.java
public class ObjectUtils{
/**
* A null safe method to detect if two objects are equal.
* @param object1
* @param object2
* @return true if either both objects are null, or equal, else returns false.
*/
public static boolean equals(Object object1, Object object2){
return object1==null ? object2==null : object1.equals(object2);
}
}
ArrayUtils.java
public class ArrayUtils{
/**
* Find the index of of an object is in given array, starting from given inclusive index.
* @param ts Array to be searched in.
* @param t Object to be searched.
* @param start The index from where the search must start.
* @return Index of the given object in the array if it is there, else -1.
*/
public static <T> int indexOf(final T[] ts, final T t, int start){
for(int i = start; i < ts.length; ++i)
if(ObjectUtils.equals(ts[i], t))
return i;
return -1;
}
/**
* Find the index of of an object is in given array, starting from 0;
* @param ts Array to be searched in.
* @param t Object to be searched.
* @return indexOf(ts, t, 0)
*/
public static <T> int indexOf(final T[] ts, final T t){
return indexOf(ts, t, 0);
}
/**
* Detect if the given object is in the given array.
* @param ts Array to be searched in.
* @param t Object to be searched.
* @return If indexOf(ts, t) is greater than -1.
*/
public static <T> boolean in(final T[] ts, final T t){
return indexOf(ts, t) > -1 ;
}
}
Wie Sie im obigen Code, dass es andere Utility - Methoden sehen ObjectUtils.equals()
und ArrayUtils.indexOf()
, die an anderen Orten verwendet wurden als gut.
Überprüfen Sie dies
String[] VALUES = new String[] {"AB","BC","CD","AE"};
String s;
for(int i=0; i< VALUES.length ; i++)
{
if ( VALUES[i].equals(s) )
{
// do your stuff
}
else{
//do your stuff
}
}
else
für jeden eingegeben Element , das nicht übereinstimmt (wenn Sie also in diesem Array nach "AB" suchen, wird es dreimal dorthin gehen, da 3 der Werte nicht "AB" sind ").
Arrays.asList () -> dann funktioniert das Aufrufen der Methode includes () immer, aber ein Suchalgorithmus ist viel besser, da Sie keinen einfachen Listen-Wrapper um das Array erstellen müssen, wie es Arrays.asList () tut .
public boolean findString(String[] strings, String desired){
for (String str : strings){
if (desired.equals(str)) {
return true;
}
}
return false; //if we get here… there is no desired String, return false.
}
Arrays.asList
ist nicht O (n). Es ist nur eine leichte Hülle. Schauen Sie sich die Implementierung an.
Wenn Sie nicht möchten, dass zwischen Groß- und Kleinschreibung unterschieden wird
Arrays.stream(VALUES).anyMatch(s::equalsIgnoreCase);
Verwenden Sie diese Array.BinarySearch(array,obj)
Option, um das angegebene Objekt im Array zu finden oder nicht.
Beispiel:
if (Array.BinarySearch(str, i) > -1)` → true --exists
false - existiert nicht
Array.BinarySearch
und Array.FindIndex
sind .NET-Methoden und existieren in Java nicht.
The array must be sorted prior to making this call. If it is not sorted, the results are undefined.
Erstellen Sie einen Booleschen Wert, der anfänglich auf false gesetzt ist. Führen Sie eine Schleife aus, um jeden Wert im Array zu überprüfen und mit dem Wert zu vergleichen, gegen den Sie prüfen. Wenn Sie jemals eine Übereinstimmung erhalten, setzen Sie den Booleschen Wert auf true und beenden Sie die Schleife. Dann behaupten Sie, dass der Boolesche Wert wahr ist.
Versuchen Sie es mit der Java 8-Prädikattestmethode
Hier ist ein vollständiges Beispiel dafür.
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class Test {
public static final List<String> VALUES = Arrays.asList("AA", "AB", "BC", "CD", "AE");
public static void main(String args[]) {
Predicate<String> containsLetterA = VALUES -> VALUES.contains("AB");
for (String i : VALUES) {
System.out.println(containsLetterA.test(i));
}
}
}
http://mytechnologythought.blogspot.com/2019/10/java-8-predicate-test-method-example.html
https://github.com/VipulGulhane1/java8/blob/master/Test.java
Die Verwendung von a Spliterator
verhindert die unnötige Erzeugung von a List
boolean found = false; // class variable
String search = "AB";
Spliterator<String> spl = Arrays.spliterator( VALUES, 0, VALUES.length );
while( (! found) && spl.tryAdvance(o -> found = o.equals( search )) );
found == true
if search
ist im Array enthalten
Dies funktioniert für Arrays von Grundelementen
public static final int[] VALUES = new int[] {1, 2, 3, 4};
boolean found = false; // class variable
int search = 2;
Spliterator<Integer> spl = Arrays.spliterator( VALUES, 0, VALUES.length );
…
Da ich mich mit Java auf niedriger Ebene beschäftige und primitive Typen wie Byte und Byte [] verwende, ist das Beste, was ich bisher von Bytes-Java erhalten habe. Https://github.com/patrickfav/bytes-java scheint eine gute Arbeit zu sein
Sie können dies auf zwei Arten überprüfen
A) Konvertieren Sie das Array in eine Zeichenfolge und überprüfen Sie die erforderliche Zeichenfolge mit der Methode .contains
String a=Arrays.toString(VALUES);
System.out.println(a.contains("AB"));
System.out.println(a.contains("BC"));
System.out.println(a.contains("CD"));
System.out.println(a.contains("AE"));
B) Dies ist eine effizientere Methode
Scanner s=new Scanner(System.in);
String u=s.next();
boolean d=true;
for(int i=0;i<VAL.length;i++)
{
if(VAL[i].equals(u)==d)
System.out.println(VAL[i] +" "+u+VAL[i].equals(u));
}