提问人:Mike Sickler 提问时间:7/15/2009 最后编辑:Peter MortensenMike Sickler 更新时间:10/30/2023 访问量:2663987
如何在 Java 中确定数组是否包含特定值?
How do I determine whether an array contains a particular value in Java?
问:
我有一个这样的值:String[]
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
鉴于,有没有一种好的方法来测试是否包含?String s
VALUES
s
答:
Arrays.asList(yourArray).contains(yourValue)
警告:这不适用于基元数组(请参阅注释)。
从 java-8 开始,您现在可以使用 Streams。
String[] values = {"AB","BC","CD","AE"};
boolean contains = Arrays.stream(values).anyMatch("s"::equals);
要检查数组 , or 是否包含值,请使用 或 或。int
double
long
IntStream
DoubleStream
LongStream
例
int[] a = {1,2,3,4};
boolean contains = IntStream.of(a).anyMatch(x -> x == 4);
评论
ArrayList
java.util.ArrayList
java.util.Arrays.ArrayList<E>
public class java.util.Arrays {private static class ArrayList<E> ... {}}
可以使用 Arrays 类对值执行二进制搜索。如果数组未排序,则必须使用同一类中的排序函数对数组进行排序,然后对其进行搜索。
评论
如果数组未排序,则必须遍历所有内容,并调用每个数组的 equals。
如果数组是排序的,你可以做一个二叉搜索,在 Arrays 类中有一个。
一般来说,如果你要进行大量的成员资格检查,你可能希望将所有内容存储在一个集合中,而不是一个数组中。
评论
Java SE 9 简明更新
引用数组是错误的。对于这种情况,我们追求的是一套。从 Java SE 9 开始,我们有 .Set.of
private static final Set<String> VALUES = Set.of(
"AB","BC","CD","AE"
);
“给定字符串 s,有没有一种好的方法来测试 VALUES 是否包含 s?”
VALUES.contains(s)
O(1)。
正确的类型,不可变,O(1) 和简洁。美丽。*
原始答案详细信息
只是为了从一开始就清除代码。我们(已更正):
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
这是一个可变的静态,FindBugs 会告诉你它非常顽皮。不要修改静态,也不允许其他代码这样做。该字段至少应为私有字段:
private static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
(请注意,您实际上可以删除该位。new String[];
引用数组仍然很糟糕,我们想要一个集合:
private static final Set<String> VALUES = new HashSet<String>(Arrays.asList(
new String[] {"AB","BC","CD","AE"}
));
(偏执狂的人,比如我自己,如果把它包起来,可能会感到更自在——它甚至可以被公开。Collections.unmodifiableSet
(*为了更深入地介绍品牌,可以预见的是,集合 API 仍然缺少不可变的集合类型,并且语法仍然太冗长了,不符合我的口味。
评论
Arrays.asList
TreeSet
O(log n)
HashSet
ObStupidAnswer(但我认为这里有一个教训):
enum Values {
AB, BC, CD, AE
}
try {
Values.valueOf(s);
return true;
} catch (IllegalArgumentException exc) {
return false;
}
评论
值得一提的是,我进行了一项测试,比较了 3 条速度建议。我生成了随机整数,将它们转换为字符串并将它们添加到数组中。然后,我搜索了可能的最高数字/字符串,这将是 .asList().contains()
使用 10K 数组大小时,结果是:
Sort & Search : 15
Binary Search : 0
asList.contains : 0
使用 100K 阵列时,结果是:
Sort & Search : 156
Binary Search : 0
asList.contains : 32
因此,如果数组是按排序顺序创建的,则二进制搜索是最快的,否则将是要走的路。如果您有很多搜索,那么可能值得对数组进行排序,以便您可以使用二进制搜索。这完全取决于您的应用。asList().contains
我认为这些是大多数人所期望的结果。以下是测试代码:
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));
}
}
评论
实际上,如果你使用 HashSet<String>正如 Tom Hawtin 所建议的那样,你不需要担心排序,而且你的速度与在预分类数组上进行二进制搜索的速度相同,甚至可能更快。
显然,这完全取决于您的代码是如何设置的,但从我的角度来看,顺序是:
在未排序的数组上:
- 哈希集
- asList(列表)
- 排序和二进制
在排序数组上:
- 哈希集
- 二元的
- asList(列表)
因此,无论哪种方式,HashSet 都是为了胜利。
评论
除了使用快速数组初始化语法之外,您还可以使用 Arrays.asList 方法以类似的方式将其直接初始化为 List,例如:
public static final List<String> STRINGS = Arrays.asList("firstString", "secondString" ...., "lastString");
然后你可以做(如上所述):
STRINGS.contains("the string you want to find");
您可以从 Apache Commons Lang 使用ArrayUtils.contains
public static boolean contains(Object[] array, Object objectToFind)
请注意,如果传递的数组是 ,则此方法返回。false
null
还有一些方法可用于各种基元数组。
例:
String[] fieldsToInclude = { "id", "name", "location" };
if ( ArrayUtils.contains( fieldsToInclude, "id" ) ) {
// Do some stuff.
}
评论
如果你有谷歌集合库,Tom的答案可以通过使用ImmutableSet(http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/ImmutableSet.html)来简化很多
这确实消除了所建议的初始化中的许多混乱
private static final Set<String> VALUES = ImmutableSet.of("AB","BC","CD","AE");
只需手动实现即可:
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;
}
起色:
该条件在方法中是恒定的。在方法调用期间,它始终计算为相同的布尔值。因此,如果输入很大,则仅评估一次此条件会更有效,我们可以根据结果在循环中使用简化/更快的条件。改进的方法:v != null
array
for
contains()
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
ArrayList
Arrays.asList(...).contains(...)
ArrayList
ArrayList.contains()
对于有限长度的数组,请使用以下命令(由 camickr 给出)。这对于重复检查来说很慢,尤其是对于较长的数组(线性搜索)。
Arrays.asList(...).contains(...)
在针对较大的元素集进行反复检查时,可获得快速性能
数组是错误的结构。使用
TreeSet
并向其添加每个元素。它对元素进行排序并具有快速方法(二进制搜索)。exist()
如果元素实现了
Comparable
&,您希望对 TreeSet
进行相应的排序:ElementClass.compareTo()
方法必须兼容:见三合会不打架?(Java Set 缺少一个项目)ElementClass.equals()
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));
否则,请使用您自己的
比较器
: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);
回报:检查某个元素的存在:
// Fast binary search through sorted elements (performance ~ log(size)): boolean containsElement = myElements.exists(someElement);
评论
TreeSet
HashSet
用于在数组中查找给定对象。Array.BinarySearch(array,obj)
例:
if (Array.BinarySearch(str, i) > -1)` → true --exists
false --不存在
评论
Array.BinarySearch
并且是 .NET 方法,在 Java 中不存在。Array.FindIndex
The array must be sorted prior to making this call. If it is not sorted, the results are undefined.
试试这个:
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");
}
使用 Java 8,您可以创建一个流并检查流中是否有任何条目匹配:"s"
String[] values = {"AB","BC","CD","AE"};
boolean sInArray = Arrays.stream(values).anyMatch("s"::equals);
或者作为通用方法:
public static <T> boolean arrayContains(T[] array, T value) {
return Arrays.stream(array).anyMatch(value::equals);
}
评论
anyMatch
"...May not evaluate the predicate on all elements if not necessary for determining the result."
使用简单的循环是最有效的方法。
boolean useLoop(String[] arr, String targetValue) {
for(String s: arr){
if(s.equals(targetValue))
return true;
}
return false;
}
由 Programcreek 提供
评论
用:
List
public static boolean useList(String[] arr, String targetValue) { return Arrays.asList(arr).contains(targetValue); }
用:
Set
public static boolean useSet(String[] arr, String targetValue) { Set<String> set = new HashSet<String>(Arrays.asList(arr)); return set.contains(targetValue); }
使用一个简单的循环:
public static boolean useLoop(String[] arr, String targetValue) { for (String s: arr) { if (s.equals(targetValue)) return true; } return false; }
用:
Arrays.binarySearch()
下面的代码是错误的,为了完整起见,这里列出了它。
binarySearch()
只能用于排序数组。你会发现下面的结果很奇怪。这是对数组进行排序时的最佳选择。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
评论
检查这个
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
开发人员经常这样做:
Set<String> set = new HashSet<String>(Arrays.asList(arr));
return set.contains(targetValue);
上面的代码有效,但不需要将列表转换为先设置。将列表转换为集合需要额外的时间。它可以像以下几点一样简单:
Arrays.asList(arr).contains(targetValue);
或
for (String s : arr) {
if (s.equals(targetValue))
return true;
}
return false;
第一个比第二个更具可读性。
使用以下命令(该方法在此代码中):contains()
ArrayUtils.in()
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;
}
}
正如您在上面的代码中看到的,还有其他实用程序方法和 ,它们在其他地方也使用过。ObjectUtils.equals()
ArrayUtils.indexOf()
一种可能的解决方案:
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");
}
}
}
在 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);
Arrays.asList() ->然后调用 contains() 方法将始终有效,但搜索算法要好得多,因为您不需要围绕数组创建轻量级列表包装器,这就是 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.
}
创建一个初始设置为 false 的布尔值。运行循环以检查数组中的每个值,并与要检查的值进行比较。如果得到匹配项,请将 boolean 设置为 true 并停止循环。然后断言布尔值为真。
如果您不希望它区分大小写
Arrays.stream(VALUES).anyMatch(s::equalsIgnoreCase);
您可以通过两种方法进行检查
A) 通过将数组转换为字符串,然后通过方法检查所需的字符串.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) 这是一种更有效的方法
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));
}
评论
尝试使用 Java 8 谓词测试方法
这是一个完整的例子。
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
当我使用原始类型 byte 和 byte[] 处理低级 Java 时,到目前为止我得到的最好的是来自 bytes-java https://github.com/patrickfav/bytes-java 这似乎是一件很好的工作
自 Java 9 以来数组可能包含重复项的最短解VALUES
List.of(VALUES).contains(s);
评论
Arrays.asList(VALUES).contains(s)
通常比 性能更高,因为它是数组的视图,不需要将所有数组值复制到一次性列表中。List.of(VALUES).contains(s)
asList()
VALUES
List
List.of()
VALUES
在下面使用 -
String[] values = {"AB","BC","CD","AE"};
String s = "A";
boolean contains = Arrays.stream(values).anyMatch(v -> v.contains(s));
评论
您可以使用 Java Streams 来确定数组是否包含特定值。下面是一个示例:
import java.util.Arrays;
public class ArrayContainsValueExample {
public static void main(String[] args) {
String[] fruits = {"apple", "banana", "orange", "kiwi", "grape"};
boolean containsOrange = Arrays.stream(fruits)
.anyMatch("orange"::equals);
if (containsOrange) {
System.out.println("The array contains 'orange'");
} else {
System.out.println("The array does not contain 'orange'");
}
}
}
在上面的例子中,我们有一个名为 的字符串类型的数组。我们使用该方法来创建数组元素的流。然后,我们调用该方法来检查流中是否有任何元素与值匹配。如果任何元素与该值匹配,该方法将返回 ,指示数组包含该值。如果没有元素与该值匹配,该方法将返回 ,指示数组不包含该值。fruits
Arrays.stream()
anyMatch()
"orange"
anyMatch()
true
anyMatch()
false
请注意,该方法会短路,这意味着一旦找到匹配项,它就会停止处理流。这使得它对大型数组很有效,因为它不需要处理所有元素。anyMatch()
Arrays.stream(VALUES).anyMatch(value -> StringUtils.equalsIgnoreCase("s", value));
评论
indexOf
contains
java.util.Arrays