Tôi có một String[]
giá trị như vậy:
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Cho String s
, có một cách tốt để kiểm tra xem VALUES
có chứa s
?
Tôi có một String[]
giá trị như vậy:
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Cho String s
, có một cách tốt để kiểm tra xem VALUES
có chứa s
?
Câu trả lời:
Arrays.asList(yourArray).contains(yourValue)
Cảnh báo: điều này không hoạt động đối với các mảng nguyên thủy (xem các bình luận).
String[] values = {"AB","BC","CD","AE"};
boolean contains = Arrays.stream(values).anyMatch("s"::equals);
Để kiểm tra xem một mảng của int
, double
hoặc long
chứa một giá trị sử dụng IntStream
, DoubleStream
hoặc LongStream
tương ứng.
int[] a = {1,2,3,4};
boolean contains = IntStream.of(a).anyMatch(x -> x == 4);
ArrayList
, nhưng không java.util.ArrayList
như bạn mong đợi, lớp thực được trả về là: java.util.Arrays.ArrayList<E>
được định nghĩa là : public class java.util.Arrays {private static class ArrayList<E> ... {}}
.
Mảng tham chiếu là xấu. Đối với trường hợp này, chúng tôi là sau một bộ. Kể từ Java SE 9 chúng ta có Set.of
.
private static final Set<String> VALUES = Set.of(
"AB","BC","CD","AE"
);
"Đã cho Chuỗi s, có cách nào tốt để kiểm tra xem GIÁ TRỊ có chứa s không?"
VALUES.contains(s)
O (1).
Các loại đúng , bất biến , O (1) và súc tích . Xinh đẹp.*
Chỉ cần xóa mã để bắt đầu. Chúng tôi đã (sửa):
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
Đây là một tĩnh có thể thay đổi mà FindBugs sẽ nói với bạn là rất nghịch ngợm. Không sửa đổi số liệu thống kê và không cho phép các mã khác cũng làm như vậy. Ở mức tối thiểu, trường phải ở chế độ riêng tư:
private static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
(Lưu ý, bạn thực sự có thể thả new String[];
bit.)
Mảng tham chiếu vẫn còn xấu và chúng tôi muốn có một bộ:
private static final Set<String> VALUES = new HashSet<String>(Arrays.asList(
new String[] {"AB","BC","CD","AE"}
));
(Những người hoang tưởng, như bản thân tôi, có thể cảm thấy thoải mái hơn nếu điều này được gói gọn Collections.unmodifiableSet
- thậm chí nó có thể được công khai.)
(* Để nói thêm một chút về thương hiệu, API bộ sưu tập có thể dự đoán vẫn còn thiếu các loại bộ sưu tập bất biến và cú pháp vẫn còn quá dài dòng, theo sở thích của tôi.)
Arrays.asList
)?
TreeSet
sẽ là O(log n)
. HashSet
s được chia tỷ lệ sao cho số phần tử trung bình trong một thùng gần như không đổi. Ít nhất là cho các mảng lên tới 2 ^ 30. Có thể có những ảnh hưởng từ các bộ nhớ cache phần cứng mà phân tích big-O bỏ qua. Cũng giả sử chức năng băm đang hoạt động hiệu quả.
Bạn có thể sử dụng ArrayUtils.contains
từ Apache Commons Lang
public static boolean contains(Object[] array, Object objectToFind)
Lưu ý rằng phương thức này trả về false
nếu mảng đã qua là null
.
Ngoài ra còn có các phương thức có sẵn cho các mảng nguyên thủy của tất cả các loại.
String[] fieldsToInclude = { "id", "name", "location" };
if ( ArrayUtils.contains( fieldsToInclude, "id" ) ) {
// Do some stuff.
}
Chỉ cần thực hiện nó bằng tay:
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;
}
Cải thiện:
Điều v != null
kiện là không đổi bên trong phương thức. Nó luôn ước tính cùng giá trị Boolean trong khi gọi phương thức. Vì vậy, nếu đầu vào array
lớn, sẽ hiệu quả hơn khi chỉ đánh giá điều kiện này một lần và chúng ta có thể sử dụng điều kiện đơn giản hóa / nhanh hơn bên trong for
vòng lặp dựa trên kết quả. contains()
Phương pháp cải tiến :
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
và ArrayList
hóa ra điều này không nhất thiết phải nhanh hơn phiên bản sử dụng Arrays.asList(...).contains(...)
. Chi phí tạo ra một ArrayList
cực kỳ nhỏ và ArrayList.contains()
sử dụng một vòng lặp thông minh hơn (thực tế nó sử dụng hai vòng lặp khác nhau) so với vòng lặp được hiển thị ở trên (JDK 7).
Bốn cách khác nhau để kiểm tra nếu một mảng chứa giá trị
1) Danh sách sử dụng:
public static boolean useList(String[] arr, String targetValue) {
return Arrays.asList(arr).contains(targetValue);
}
2) Sử dụng Set:
public static boolean useSet(String[] arr, String targetValue) {
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
}
3) Sử dụng một vòng lặp đơn giản:
public static boolean useLoop(String[] arr, String targetValue) {
for (String s: arr) {
if (s.equals(targetValue))
return true;
}
return false;
}
4) Sử dụng Arrays.binarySearch ():
Mã dưới đây là sai, nó được liệt kê ở đây cho đầy đủ. binarySearch () CHỈ có thể được sử dụng trên các mảng được sắp xếp. Bạn sẽ tìm thấy kết quả là kỳ lạ dưới đây. Đây là tùy chọn tốt nhất khi mảng được sắp xếp.
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)
là chính xác, chỉ cần kiểm tra các tài liệu , họ nói "Lưu ý rằng điều này đảm bảo rằng giá trị trả về sẽ> = 0 khi và chỉ khi tìm thấy khóa".
Nếu mảng không được sắp xếp, bạn sẽ phải lặp đi lặp lại mọi thứ và thực hiện cuộc gọi bằng nhau trên mỗi mảng.
Nếu mảng được sắp xếp, bạn có thể thực hiện tìm kiếm nhị phân, có một mảng trong lớp Mảng .
Nói chung, nếu bạn định thực hiện nhiều kiểm tra thành viên, bạn có thể muốn lưu trữ mọi thứ trong Tập hợp, không phải trong một mảng.
Để biết giá trị của nó, tôi đã chạy thử nghiệm so sánh 3 gợi ý về tốc độ. Tôi đã tạo các số nguyên ngẫu nhiên, chuyển đổi chúng thành Chuỗi và thêm chúng vào một mảng. Sau đó tôi đã tìm kiếm số / chuỗi cao nhất có thể, đó sẽ là trường hợp xấu nhất choasList().contains()
.
Khi sử dụng kích thước mảng 10K, kết quả là:
Sắp xếp và tìm kiếm: 15 Tìm kiếm nhị phân: 0 asList.contains: 0
Khi sử dụng mảng 100K, kết quả là:
Sắp xếp và tìm kiếm: 156 Tìm kiếm nhị phân: 0 asList.contains: 32
Vì vậy, nếu mảng được tạo theo thứ tự sắp xếp, tìm kiếm nhị phân là nhanh nhất, nếu không thì asList().contains
đó sẽ là cách để đi. Nếu bạn có nhiều tìm kiếm, thì có thể đáng để sắp xếp mảng để bạn có thể sử dụng tìm kiếm nhị phân. Tất cả phụ thuộc vào ứng dụng của bạn.
Tôi nghĩ đó là những kết quả mà hầu hết mọi người mong đợi. Đây là mã kiểm tra:
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));
}
}
Thay vì sử dụng cú pháp khởi tạo mảng nhanh quá, bạn chỉ có thể khởi tạo nó dưới dạng Danh sách theo cách tương tự bằng cách sử dụng phương thức Arrays.asList, ví dụ:
public static final List<String> STRINGS = Arrays.asList("firstString", "secondString" ...., "lastString");
Sau đó, bạn có thể làm (như trên):
STRINGS.contains("the string you want to find");
Với Java 8, bạn có thể tạo một luồng và kiểm tra xem có bất kỳ mục nào trong luồng phù hợp không "s"
:
String[] values = {"AB","BC","CD","AE"};
boolean sInArray = Arrays.stream(values).anyMatch("s"::equals);
Hoặc như một phương pháp chung:
public static <T> boolean arrayContains(T[] array, T value) {
return Arrays.stream(array).anyMatch(value::equals);
}
anyMatch
JavaDoc cũng nói rằng "...May not evaluate the predicate on all elements if not necessary for determining the result."
nó có thể không cần tiếp tục xử lý sau khi tìm thấy kết quả khớp.
Bạn có thể sử dụng lớp Mảng để thực hiện tìm kiếm nhị phân cho giá trị. Nếu mảng của bạn không được sắp xếp, bạn sẽ phải sử dụng các hàm sắp xếp trong cùng một lớp để sắp xếp mảng, sau đó tìm kiếm qua nó.
ObStoolAnswer (nhưng tôi nghĩ có một bài học ở đây ở đâu đó):
enum Values {
AB, BC, CD, AE
}
try {
Values.valueOf(s);
return true;
} catch (IllegalArgumentException exc) {
return false;
}
Trên thực tế, nếu bạn sử dụng Hashset <String> như Tom Hawtin đề xuất, bạn không cần phải lo lắng về việc sắp xếp và tốc độ của bạn cũng giống như với tìm kiếm nhị phân trên một mảng được định sẵn, thậm chí có thể nhanh hơn.
Tất cả phụ thuộc vào cách mã của bạn được thiết lập, rõ ràng, nhưng từ nơi tôi đứng, thứ tự sẽ là:
Trên một mảng chưa được sắp xếp :
Trên một mảng được sắp xếp:
Vì vậy, một trong hai cách, Hashset cho chiến thắng.
Nếu bạn có thư viện bộ sưu tập google, câu trả lời của Tom có thể được đơn giản hóa rất nhiều bằng cách sử dụng Immutable Set (http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/Immutableset.html)
Điều này thực sự loại bỏ rất nhiều lộn xộn từ khởi tạo được đề xuất
private static final Set<String> VALUES = ImmutableSet.of("AB","BC","CD","AE");
Một giải pháp khả thi:
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");
}
}
}
Các nhà phát triển thường làm:
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
Đoạn mã trên hoạt động, nhưng không cần phải chuyển đổi danh sách để đặt đầu tiên. Chuyển đổi một danh sách thành một bộ đòi hỏi thêm thời gian. Nó có thể đơn giản như:
Arrays.asList(arr).contains(targetValue);
hoặc là
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;
Cái đầu tiên dễ đọc hơn cái thứ hai.
Sử dụng một vòng lặp đơn giản là cách hiệu quả nhất để làm điều này.
boolean useLoop(String[] arr, String targetValue) {
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;
}
Courtesy để Programcreek
Trong Java 8 sử dụng Luồng.
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);
Đối với các mảng có độ dài giới hạn, sử dụng như sau (như được đưa ra bởi camickr ). Điều này chậm đối với các kiểm tra lặp đi lặp lại, đặc biệt đối với các mảng dài hơn (tìm kiếm tuyến tính).
Arrays.asList(...).contains(...)
Để có hiệu suất nhanh nếu bạn liên tục kiểm tra một bộ phần tử lớn hơn
Một mảng là cấu trúc sai. Sử dụng a TreeSet
và thêm từng yếu tố cho nó. Nó sắp xếp các phần tử và có một exist()
phương thức nhanh (tìm kiếm nhị phân).
Nếu các yếu tố thực hiện Comparable
& bạn muốn TreeSet
sắp xếp phù hợp:
ElementClass.compareTo()
Phương pháp phải tương thích với ElementClass.equals()
: xem Triads không hiển thị để chiến đấu? (Java Set thiếu một mục)
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));
Nếu không, sử dụng của riêng bạ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);
Phần thưởng: kiểm tra sự tồn tại của một số phần tử:
// Fast binary search through sorted elements (performance ~ log(size)):
boolean containsElement = myElements.exists(someElement);
TreeSet
? HashSet
nhanh hơn (O (1)) và không yêu cầu đặt hàng.
Thử cái này:
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");
}
Sử dụng như sau ( contains()
phương thức ArrayUtils.in()
trong mã này):
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 ;
}
}
Như bạn có thể thấy trong đoạn mã trên, có những phương thức tiện ích khác ObjectUtils.equals()
và ArrayUtils.indexOf()
cũng được sử dụng ở những nơi khác.
Kiểm tra điều này
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
cho mọi mục không khớp (vì vậy nếu bạn đang tìm kiếm "AB" trong mảng đó, nó sẽ đến đó 3 lần, vì 3 trong số các giá trị không phải là "AB ").
Arrays.asList () -> sau đó gọi phương thức chứa () sẽ luôn hoạt động, nhưng thuật toán tìm kiếm sẽ tốt hơn nhiều vì bạn không cần phải tạo một trình bao bọc danh sách nhẹ xung quanh mảng, đó là những gì Arrays.asList () làm .
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
không phải là O (n). Nó chỉ là một cái bọc nhẹ. Có một cái nhìn vào việc thực hiện.
Nếu bạn không muốn nó là trường hợp nhạy cảm
Arrays.stream(VALUES).anyMatch(s::equalsIgnoreCase);
Sử dụng Array.BinarySearch(array,obj)
để tìm đối tượng đã cho trong mảng hay không.
Thí dụ:
if (Array.BinarySearch(str, i) > -1)` → true --exists
sai - không tồn tại
Array.BinarySearch
và Array.FindIndex
là các phương thức .NET và không tồn tại trong Java.
The array must be sorted prior to making this call. If it is not sorted, the results are undefined.
Thử sử dụng phương thức kiểm tra vị ngữ Java 8
Dưới đây là một ví dụ đầy đủ về nó.
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));
}
}
}
https://github.com/VipulGulhane1/java8/blob/master/Test.java
việc sử dụng Spliterator
ngăn chặn việc tạo ra một 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
nếu search
được chứa trong mảng
điều này không làm việc cho các mảng nguyên thủy
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 );
…
Khi tôi đang xử lý Java mức thấp bằng cách sử dụng kiểu byte và byte nguyên thủy [], điều tốt nhất cho đến nay tôi nhận được là từ byte-java https://github.com/patrickfav/bytes-java có vẻ là một công việc tốt
Bạn có thể kiểm tra nó bằng hai phương pháp
A) Bằng cách chuyển đổi mảng thành chuỗi và sau đó kiểm tra chuỗi yêu cầu bằng phương thức .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) đây là một phương pháp hiệu quả hơn
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));
}