Ben böyle String[]
değerleri ile bir var :
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Verilen String s
, içerip VALUES
içermediğini test etmenin iyi bir yolu var mı s
?
Ben böyle String[]
değerleri ile bir var :
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Verilen String s
, içerip VALUES
içermediğini test etmenin iyi bir yolu var mı s
?
Yanıtlar:
Arrays.asList(yourArray).contains(yourValue)
Uyarı: Bu, ilkel diziler için geçerli değildir (yorumlara bakın).
String[] values = {"AB","BC","CD","AE"};
boolean contains = Arrays.stream(values).anyMatch("s"::equals);
Bir dizi kontrol etmek için int
, double
ya da long
bir değer kullanımını içerir IntStream
, DoubleStream
ya da LongStream
sırasıyla.
int[] a = {1,2,3,4};
boolean contains = IntStream.of(a).anyMatch(x -> x == 4);
ArrayList
, ama java.util.ArrayList
beklediğiniz gibi, gerçek sınıf döndürülen: java.util.Arrays.ArrayList<E>
olarak tanımlanır: public class java.util.Arrays {private static class ArrayList<E> ... {}}
.
Referans dizileri bozuk. Bu durumda bir set peşindeyiz. Java SE 9'dan beri var Set.of
.
private static final Set<String> VALUES = Set.of(
"AB","BC","CD","AE"
);
"String'ler verildiğinde, VALUES öğesinin s içerip içermediğini test etmenin iyi bir yolu var mı?"
VALUES.contains(s)
O (1).
Sağ türü , değişmez , O (1) ve kısa . Güzel.*
Sadece başlamak için kodu temizlemek için. Biz (düzelttik):
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Bu, FindBugs'in size çok yaramaz olduğunu söyleyeceği değiştirilebilir bir statiktir. Statiği değiştirmeyin ve diğer kodların da buna izin vermeyin. Mutlak minimumda, alan özel olmalıdır:
private static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
(Not, aslında new String[];
biraz düşebilir .)
Referans dizileri hala kötü ve bir dizi istiyoruz:
private static final Set<String> VALUES = new HashSet<String>(Arrays.asList(
new String[] {"AB","BC","CD","AE"}
));
(Kendim gibi paranoyak insanlar, eğer sarılırsa daha rahat hissedebilir Collections.unmodifiableSet
- o zaman halka açık bile olabilir.)
(* Markada biraz daha fazla olmak için, koleksiyon API'sı tahmin edilemeyecek şekilde hala değişmez koleksiyon türlerini kaçırıyor ve sözdizimi, zevklerim için hala çok ayrıntılı.)
Arrays.asList
)?
TreeSet
olur O(log n)
. HashSet
bir kovadaki ortalama eleman sayısı kabaca sabit olacak şekilde ölçeklendirilir. En azından 2 ^ 30'a kadar diziler için. Diyelim ki big-O analizinin göz ardı ettiği donanım önbellekleri olabilir. Ayrıca hash işlevinin etkili bir şekilde çalıştığını varsayar.
Sen kullanabilirsiniz ArrayUtils.contains
gelen Apache Commons Lang
public static boolean contains(Object[] array, Object objectToFind)
false
Geçirilen dizi ise bu yöntemin döndüğünü unutmayın null
.
Her çeşit ilkel diziler için de yöntemler vardır.
String[] fieldsToInclude = { "id", "name", "location" };
if ( ArrayUtils.contains( fieldsToInclude, "id" ) ) {
// Do some stuff.
}
Sadece elle uygulayın:
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;
}
Gelişme:
v != null
Durum yöntemi içinde sabittir. Yöntem çağrısı sırasında her zaman aynı Boole değerini değerlendirir. Dolayısıyla girdi array
büyükse, bu durumu yalnızca bir kez değerlendirmek daha verimlidir for
ve sonuca bağlı olarak döngü içinde basitleştirilmiş / daha hızlı bir koşul kullanabiliriz . Geliştirilmiş contains()
yöntem:
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
ve ArrayList
bunun sürümün kullanılmasından daha hızlı olmadığı ortaya çıkıyor Arrays.asList(...).contains(...)
. A oluşturma yükü ArrayList
son derece küçüktür ve ArrayList.contains()
yukarıda gösterilenlerden (JDK 7) daha akıllı bir döngü kullanır (aslında iki farklı döngü kullanır).
Bir Dizinin Değer İçerip İçermediğini Kontrol Etmenin Dört Farklı Yolu
1) Liste Kullanarak:
public static boolean useList(String[] arr, String targetValue) {
return Arrays.asList(arr).contains(targetValue);
}
2) Set kullanarak:
public static boolean useSet(String[] arr, String targetValue) {
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
}
3) Basit bir döngü kullanarak:
public static boolean useLoop(String[] arr, String targetValue) {
for (String s: arr) {
if (s.equals(targetValue))
return true;
}
return false;
}
4) Arrays.binarySearch () kullanılması:
Aşağıdaki kod yanlış, tamlık için burada listelenmiştir. binarySearch () SADECE sıralı dizilerde kullanılabilir. Sonucun garip olduğunu göreceksiniz. Dizi sıralandığında bu en iyi seçenektir.
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)
doğruydu, sadece dokümanları kontrol edin , "Bunun dönüş değerinin yalnızca anahtar bulunursa> = 0 olacağını garanti ettiğini" söylediler.
Dizi sıralanmamışsa, her şeyi yinelemeniz ve her birine eşittir çağrısı yapmanız gerekir.
Dizi sıralanırsa, ikili bir arama yapabilirsiniz, Diziler sınıfında bir tane var.
Genel olarak konuşursak, çok sayıda üyelik kontrolü yapacaksanız, her şeyi bir dizide değil, bir Sette saklamak isteyebilirsiniz.
Değeri için hız için 3 önerileri karşılaştıran bir test yaptım. Rastgele tamsayılar oluşturdum, bunları bir String'e dönüştürdüm ve bir diziye ekledim. Daha sonra için en kötü durum senaryosu olacağını mümkün olan en yüksek sayı / dize aradı asList().contains()
.
10K dizi boyutu kullanıldığında sonuçlar şunlardı:
Sırala ve Ara: 15 İkili Arama: 0 asList.contains: 0
100K dizisi kullanıldığında sonuçlar şunlardı:
Sırala ve Ara: 156 İkili Arama: 0 asList. içerir: 32
Yani dizi sıralı olarak oluşturulursa ikili arama en hızlıdır, aksi takdirde asList().contains
gitmek için bir yol olacaktır. Çok sayıda aramanız varsa, ikili aramayı kullanabilmeniz için diziyi sıralamak faydalı olabilir. Her şey uygulamanıza bağlıdır.
Bunların çoğu insanın bekleyeceği sonuçlar olduğunu düşünürüm. İşte test kodu:
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));
}
}
Hızlı dizi başlatma sözdizimini de kullanmak yerine, Arrays.asList yöntemini kullanarak hemen benzer bir şekilde Liste olarak başlatabilirsiniz, örneğin:
public static final List<String> STRINGS = Arrays.asList("firstString", "secondString" ...., "lastString");
Sonra yapabilirsin (yukarıdaki gibi):
STRINGS.contains("the string you want to find");
Java 8 ile bir akış oluşturabilir ve akıştaki herhangi bir girişin eşleşip eşleşmediğini kontrol edebilirsiniz "s"
:
String[] values = {"AB","BC","CD","AE"};
boolean sInArray = Arrays.stream(values).anyMatch("s"::equals);
Veya genel bir yöntem olarak:
public static <T> boolean arrayContains(T[] array, T value) {
return Arrays.stream(array).anyMatch(value::equals);
}
anyMatch
JavaDoc bunu belirtir, bu "...May not evaluate the predicate on all elements if not necessary for determining the result."
nedenle bir eşleşme bulduktan sonra işlemeye devam etmesi gerekmeyebilir.
Değer için ikili arama yapmak üzere Arrays sınıfını kullanabilirsiniz . Diziniz sıralanmamışsa, diziyi sıralamak için aynı sınıftaki sıralama işlevlerini kullanmanız ve ardından onu aramanız gerekir.
ObStupidAnswer (ama burada bir yerde bir ders olduğunu düşünüyorum):
enum Values {
AB, BC, CD, AE
}
try {
Values.valueOf(s);
return true;
} catch (IllegalArgumentException exc) {
return false;
}
Aslında, Tom Hawtin'in önerdiği gibi HashSet <String> kullanıyorsanız, sıralama konusunda endişelenmenize gerek yoktur ve hızınız, önceden belirlenmiş bir dizide ikili arama ile aynıdır, muhtemelen daha da hızlıdır.
Her şey kodunuzun açık bir şekilde nasıl ayarlandığına bağlıdır, ancak durduğum yerden sipariş şu şekilde olacaktır:
Üzerinde sıralanmamış dizisi:
Sıralı bir dizide:
Her iki şekilde de, HashSet kazanmak için.
Google koleksiyon kitaplığınız varsa Tom'un yanıtı ImmutableSet (http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/ImmutableSet.html) kullanılarak çok basitleştirilebilir.
Bu, önerilen başlatma işleminden çok fazla karmaşayı ortadan kaldırır
private static final Set<String> VALUES = ImmutableSet.of("AB","BC","CD","AE");
Olası bir çözüm:
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");
}
}
}
Geliştiriciler genellikle şunları yapar:
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
Yukarıdaki kod çalışır, ancak önce bir listeyi ayarlamak için dönüştürmeye gerek yoktur. Bir listeyi sete dönüştürmek fazladan zaman gerektirir. Bu kadar basit olabilir:
Arrays.asList(arr).contains(targetValue);
veya
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;
Birincisi ikincisinden daha okunabilir.
Basit bir döngü kullanmak bunu yapmanın en etkili yoludur.
boolean useLoop(String[] arr, String targetValue) {
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;
}
Programcreek izniyle
In Java 8 Akışları kullanın.
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);
Sınırlı uzunlukta diziler için aşağıdakileri kullanın ( camickr tarafından verildiği gibi ). Bu, özellikle daha uzun diziler için tekrarlanan kontroller için yavaştır (doğrusal arama).
Arrays.asList(...).contains(...)
Daha büyük bir eleman setini tekrar tekrar kontrol ederseniz hızlı performans için
Dizi yanlış yapıdır. A öğesini kullanın TreeSet
ve her öğeyi buna ekleyin. Elemanları sıralar ve hızlı bir exist()
metoda sahiptir (ikili arama).
Elemanlar uygulanırsa Comparable
ve TreeSet
buna göre sıralanmak istiyorsanız :
ElementClass.compareTo()
yöntemi aşağıdakilerle uyumlu olmalıdır ElementClass.equals()
: bkz. Triadlar savaşmaya gelmiyor mu? (Java Seti'nde bir öğe eksik)
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));
Aksi takdirde, kendiniz kullanın 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);
Kazanç: bazı unsurların varlığını kontrol edin:
// Fast binary search through sorted elements (performance ~ log(size)):
boolean containsElement = myElements.exists(someElement);
TreeSet
? HashSet
daha hızlıdır (O (1)) ve sipariş gerektirmez.
Bunu dene:
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");
}
Aşağıdakileri kullanın ( contains()
yöntem ArrayUtils.in()
bu koddadır):
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 ;
}
}
Yukarıdaki kodda da görebileceğiniz gibi, başka yardımcı yöntemler de vardır ObjectUtils.equals()
ve ArrayUtils.indexOf()
bunlar başka yerlerde de kullanılmıştır.
Şuna göz at
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
için değerini girer (bu nedenle bu dizide "AB" arıyorsanız, 3 kez oraya gider, çünkü değerlerin 3'ü "AB" ").
Arrays.asList () -> sonra include () yöntemini çağırmak her zaman işe yarayacaktır, ancak dizi etrafında hafif bir liste sarmalayıcısı oluşturmanız gerekmediğinden bir arama algoritması çok daha iyidir, bu da Arrays.asList () 'in yaptığı şeydir .
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
O (n) değildir. Sadece hafif bir ambalaj. Uygulamaya bir göz atın.
Büyük / küçük harfe duyarlı olmasını istemiyorsanız
Arrays.stream(VALUES).anyMatch(s::equalsIgnoreCase);
Array.BinarySearch(array,obj)
Dizide verilen nesneyi bulmak için kullanın .
Misal:
if (Array.BinarySearch(str, i) > -1)` → true --exists
yanlış - mevcut değil
Array.BinarySearch
ve Array.FindIndex
.NET yöntemleridir ve Java'da yoktur.
The array must be sorted prior to making this call. If it is not sorted, the results are undefined.
Başlangıçta false olarak ayarlanmış bir boolean oluşturun. Dizideki her değeri kontrol etmek ve kontrol ettiğiniz değerle karşılaştırmak için bir döngü çalıştırın. Bir eşleşme alırsanız, boolean değerini true olarak ayarlayın ve döngüyü durdurun. Sonra boolean'ın doğru olduğunu iddia edin.
Java 8 yüklem test yöntemini kullanmayı deneyin
İşte bunun tam bir örneği.
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
bir kullanımı Spliterator
, bir 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
search
dizide yer alıyorsa
Bu does ilkelle diziler için çalışma
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 );
…
İlkel tip bayt ve bayt [] kullanarak düşük seviyeli Java ile uğraştığım için, şimdiye kadarki en iyisi bytes-java'dan https://github.com/patrickfav/bytes-java iyi bir iş parçası gibi görünüyor
İki yöntemle kontrol edebilirsiniz
A) Diziyi dizeye dönüştürüp gerekli dizeyi .contains yöntemiyle kontrol ederek
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) bu daha etkili bir yöntemdir
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));
}