Mam String[]
z takimi wartościami:
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Biorąc pod uwagę String s
, czy istnieje dobry sposób na sprawdzenie, czy VALUES
zawiera s
?
Mam String[]
z takimi wartościami:
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Biorąc pod uwagę String s
, czy istnieje dobry sposób na sprawdzenie, czy VALUES
zawiera s
?
Odpowiedzi:
Arrays.asList(yourArray).contains(yourValue)
Ostrzeżenie: nie działa to dla tablic prymitywów (patrz komentarze).
String[] values = {"AB","BC","CD","AE"};
boolean contains = Arrays.stream(values).anyMatch("s"::equals);
Aby sprawdzić, czy tablica int
, double
lub long
zawiera wartość użytkową IntStream
, DoubleStream
lub LongStream
odpowiednio.
int[] a = {1,2,3,4};
boolean contains = IntStream.of(a).anyMatch(x -> x == 4);
ArrayList
, ale nie java.util.ArrayList
jak można oczekiwać, prawdziwa klasa zwracany jest: java.util.Arrays.ArrayList<E>
zdefiniowana jako: public class java.util.Arrays {private static class ArrayList<E> ... {}}
.
Macierze referencyjne są złe. W tym przypadku jesteśmy po secie. Od wersji Java SE 9 mamy Set.of
.
private static final Set<String> VALUES = Set.of(
"AB","BC","CD","AE"
);
„Biorąc pod uwagę ciąg znaków s, czy istnieje dobry sposób na sprawdzenie, czy WARTOŚCI zawierają s?”
VALUES.contains(s)
O (1).
Odpowiedni rodzaj , niezmienny , O (1) i zwięzły . Piękny.*
Po prostu wyczyść kod na początek. Mamy (poprawione):
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Jest to zmienna statyczna, którą FindBugs powie ci, że jest bardzo niegrzeczna. Nie modyfikuj statyki i nie zezwalaj na to również innym kodom. Przy absolutnym minimum pole powinno być prywatne:
private static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
(Uwaga, możesz upuścić new String[];
bit.)
Tablice referencyjne są nadal złe i chcemy zestawu:
private static final Set<String> VALUES = new HashSet<String>(Arrays.asList(
new String[] {"AB","BC","CD","AE"}
));
(Ludzie z paranoikami, tacy jak ja, mogą czuć się bardziej swobodnie, jeśli się w to zapakuje Collections.unmodifiableSet
- może to nawet zostać upublicznione).
(* Mówiąc trochę więcej o marce, interfejs API kolekcji wciąż prawdopodobnie nie ma niezmiennych typów kolekcji, a składnia jest wciąż zbyt szczegółowa, jak na mój gust).
Arrays.asList
)?
TreeSet
byłoby O(log n)
. HashSet
s są skalowane w taki sposób, że średnia liczba elementów w wiadrze jest z grubsza stała. Przynajmniej dla tablic do 2 ^ 30. Mogą występować wpływy, powiedzmy, pamięci podręcznych sprzętu, które ignorowane są w analizie wielkiej litery. Zakłada również, że funkcja skrótu działa skutecznie.
Możesz używać ArrayUtils.contains
z Apache Commons Lang
public static boolean contains(Object[] array, Object objectToFind)
Zauważ, że ta metoda zwraca, false
jeśli przekazana tablica to null
.
Dostępne są również metody prymitywnych tablic wszelkiego rodzaju.
String[] fieldsToInclude = { "id", "name", "location" };
if ( ArrayUtils.contains( fieldsToInclude, "id" ) ) {
// Do some stuff.
}
Po prostu zaimplementuj go ręcznie:
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;
}
Poprawa:
v != null
Warunkiem jest stała wewnątrz metody. Zawsze zwraca tę samą wartość logiczną podczas wywołania metody. Więc jeśli dane wejściowe array
są duże, bardziej efektywna jest ocena tego warunku tylko raz, a my możemy zastosować uproszczony / szybszy warunek w for
pętli na podstawie wyniku. Ulepszona contains()
metoda:
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
i ArrayList
okaże się, że niekoniecznie jest to szybsze niż wersja Arrays.asList(...).contains(...)
. Narzut związany z tworzeniem pliku ArrayList
jest bardzo mały i ArrayList.contains()
wykorzystuje bardziej inteligentną pętlę (w rzeczywistości wykorzystuje dwie różne pętle) niż ta pokazana powyżej (JDK 7).
Cztery różne sposoby sprawdzania, czy tablica zawiera wartość
1) Korzystanie z listy:
public static boolean useList(String[] arr, String targetValue) {
return Arrays.asList(arr).contains(targetValue);
}
2) Za pomocą zestawu:
public static boolean useSet(String[] arr, String targetValue) {
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
}
3) Za pomocą prostej pętli:
public static boolean useLoop(String[] arr, String targetValue) {
for (String s: arr) {
if (s.equals(targetValue))
return true;
}
return false;
}
4) Za pomocą Arrays.binarySearch ():
Poniższy kod jest niepoprawny, jest podany tutaj dla kompletności. Funkcja binarySearch () może być używana TYLKO na posortowanych tablicach. Przekonasz się, że wynik jest dziwny poniżej. Jest to najlepsza opcja podczas sortowania tablicy.
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
Jeśli tablica nie zostanie posortowana, będziesz musiał iterować wszystko i wykonać wywołanie równości na każdym z nich.
Jeśli tablica jest posortowana, możesz przeprowadzić wyszukiwanie binarne, jest ona w klasie Arrays .
Ogólnie rzecz biorąc, jeśli zamierzasz przeprowadzić wiele kontroli członkostwa, możesz chcieć przechowywać wszystko w zestawie, a nie w tablicy.
Za to, co warto, przeprowadziłem test porównujący 3 sugestie dotyczące prędkości. Wygenerowałem losowe liczby całkowite, przekonwertowałem je na String i dodałem do tablicy. Następnie szukałem najwyższej możliwej liczby / łańcucha, co byłoby najgorszym scenariuszem dla asList().contains()
.
W przypadku zastosowania tablicy o rozmiarze 10 KB wyniki były następujące:
Sortuj i szukaj: 15 Wyszukiwanie binarne: 0 asList.contains: 0
W przypadku zastosowania tablicy 100 KB wyniki były następujące:
Sortuj i szukaj: 156 Wyszukiwanie binarne: 0 asList.contains: 32
Więc jeśli tablica jest tworzona w posortowanej kolejności, wyszukiwanie binarne jest najszybsze, w przeciwnym razie asList().contains
byłoby to właściwe. Jeśli masz wiele wyszukiwań, warto posortować tablicę, aby móc korzystać z wyszukiwania binarnego. Wszystko zależy od twojej aplikacji.
Sądzę, że są to wyniki, których większość ludzi by się spodziewała. Oto kod testowy:
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));
}
}
Zamiast używać również składni szybkiego inicjowania tablicy, możesz po prostu zainicjować ją jako Listę w podobny sposób, używając metody Arrays.asList, np .:
public static final List<String> STRINGS = Arrays.asList("firstString", "secondString" ...., "lastString");
Następnie możesz zrobić (jak wyżej):
STRINGS.contains("the string you want to find");
W Javie 8 możesz utworzyć strumień i sprawdzić, czy wpisy w strumieniu są zgodne "s"
:
String[] values = {"AB","BC","CD","AE"};
boolean sInArray = Arrays.stream(values).anyMatch("s"::equals);
Lub jako metoda ogólna:
public static <T> boolean arrayContains(T[] array, T value) {
return Arrays.stream(array).anyMatch(value::equals);
}
anyMatch
JavaDoc stwierdza, że "...May not evaluate the predicate on all elements if not necessary for determining the result."
tak, więc może nie być konieczne kontynuowanie przetwarzania po znalezieniu dopasowania.
Za pomocą klasy Arrays można wyszukiwać binarnie wartość. Jeśli twoja tablica nie jest posortowana, będziesz musiał użyć funkcji sortowania w tej samej klasie, aby posortować tablicę, a następnie przeszukaj ją.
ObStupidAnswer (ale myślę, że gdzieś jest tu lekcja):
enum Values {
AB, BC, CD, AE
}
try {
Values.valueOf(s);
return true;
} catch (IllegalArgumentException exc) {
return false;
}
W rzeczywistości, jeśli użyjesz HashSet <String> zgodnie z sugestią Toma Hawtina, nie musisz się martwić sortowaniem, a Twoja prędkość jest taka sama jak w przypadku wyszukiwania binarnego na wstępnie ustawionej tablicy, prawdopodobnie nawet szybciej.
Wszystko zależy oczywiście od tego, jak skonfigurowany jest twój kod, ale z mojego punktu widzenia kolejność byłaby następująca:
W nieposortowanej tablicy:
W posortowanej tablicy:
Tak czy inaczej, HashSet dla wygranej.
Jeśli masz bibliotekę kolekcji Google, odpowiedź Toma można znacznie uprościć, używając ImmutableSet (http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/ImmutableSet.html)
To naprawdę usuwa wiele bałaganu z proponowanej inicjalizacji
private static final Set<String> VALUES = ImmutableSet.of("AB","BC","CD","AE");
Jedno możliwe rozwiązanie:
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");
}
}
}
Programiści często:
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
Powyższy kod działa, ale nie trzeba konwertować listy, aby ustawić ją jako pierwszą. Przekształcenie listy w zestaw wymaga dodatkowego czasu. Może to być tak proste jak:
Arrays.asList(arr).contains(targetValue);
lub
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;
Pierwszy jest bardziej czytelny niż drugi.
Użycie prostej pętli jest najbardziej wydajnym sposobem na zrobienie tego.
boolean useLoop(String[] arr, String targetValue) {
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;
}
Dzięki uprzejmości Programcreek
W Javie 8 używaj strumieni.
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);
W przypadku tablic o ograniczonej długości użyj następujących (podanych przez camickr ). Jest to powolne w przypadku powtarzanych kontroli, szczególnie w przypadku dłuższych tablic (wyszukiwanie liniowe).
Arrays.asList(...).contains(...)
Dla szybkiej wydajności, jeśli wielokrotnie sprawdzasz w stosunku do większego zestawu elementów
Tablica ma niewłaściwą strukturę. Użyj a TreeSet
i dodaj do niego każdy element. Sortuje elementy i ma szybką exist()
metodę (wyszukiwanie binarne).
Jeśli elementy są zaimplementowane Comparable
i chcesz odpowiednio TreeSet
posortować:
ElementClass.compareTo()
metoda musi być kompatybilna z ElementClass.equals()
: patrz Triady nie pojawiają się do walki? (Java Set brakuje elementu)
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));
W przeciwnym razie użyj własnego 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);
Wypłata: sprawdź istnienie jakiegoś elementu:
// Fast binary search through sorted elements (performance ~ log(size)):
boolean containsElement = myElements.exists(someElement);
TreeSet
? HashSet
jest szybszy (O (1)) i nie wymaga zamawiania.
Spróbuj tego:
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");
}
Użyj następującego ( contains()
metoda znajduje się ArrayUtils.in()
w tym kodzie):
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 ;
}
}
Jak widać w powyższym kodzie, że istnieją inne metody narzędziowe ObjectUtils.equals()
i ArrayUtils.indexOf()
, które były wykorzystywane w innych miejscach.
Sprawdź to
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
dla każdego elementu, który nie zgadza się (tak, jeśli szukasz dla „AB” w tej tablicy, to będzie tam 3 razy, ponieważ 3 wartości nie są „AB „).
Arrays.asList () -> wtedy wywoływanie metody zawiera () zawsze będzie działać, ale algorytm wyszukiwania jest znacznie lepszy, ponieważ nie trzeba tworzyć lekkiego opakowania listy wokół tablicy, co robi Arrays.asList () .
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
nie jest O (n). To tylko lekkie opakowanie. Zobacz implementację.
Jeśli nie chcesz, aby wielkość liter była uwzględniana
Arrays.stream(VALUES).anyMatch(s::equalsIgnoreCase);
Służy Array.BinarySearch(array,obj)
do znajdowania danego obiektu w tablicy lub nie.
Przykład:
if (Array.BinarySearch(str, i) > -1)` → true --exists
false - nie istnieje
Array.BinarySearch
i Array.FindIndex
są metodami .NET i nie istnieją w Javie.
The array must be sorted prior to making this call. If it is not sorted, the results are undefined.
Utwórz wartość logiczną początkowo ustawioną na false. Uruchom pętlę, aby sprawdzić każdą wartość w tablicy i porównać z wartością, którą sprawdzasz. Jeśli kiedykolwiek otrzymasz dopasowanie, ustaw wartość logiczną na true i zatrzymaj zapętlenie. Następnie zapewnij, że wartość logiczna jest prawdziwa.
Spróbuj użyć predykcyjnej metody testowej Java 8
Oto pełny tego przykład.
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
użycie a Spliterator
zapobiega niepotrzebnemu wygenerowaniu 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
jeśli search
jest zawarty w tablicy
to czyni pracę dla tablic prymitywów
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 );
…
Ponieważ mam do czynienia z językiem Java niskiego poziomu przy użyciu pierwotnych typów bajtów i bajtów [], najlepsze, jakie dotychczas uzyskałem, to bajty-java https://github.com/patrickfav/bytes-java wydaje się być świetnym kawałkiem pracy
Możesz to sprawdzić na dwa sposoby
A) Konwertując tablicę na ciąg, a następnie sprawdź wymagany ciąg metodą .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) jest to bardziej skuteczna metoda
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));
}