如何确定数组是否包含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); 

要检查intdoublelong数组是否包含值, LongStream分别使用IntStreamDoubleStreamLongStream

 int[] a = {1,2,3,4}; boolean contains = IntStream.of(a).anyMatch(x -> x == 4); 

只是为了开始清除代码。 我们已经(更正):

 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 VALUES = new HashSet(Arrays.asList( new String[] {"AB","BC","CD","AE"} )); 

(偏执狂的人,比如我自己,如果将它包装在Collections.unmodifiableSet ,可能会感到更放心 – 它甚至可以公开。)

“鉴于String,有没有一种很好的方法来测试VALUES是否包含s?”

 VALUES.contains(s) 

O(1)。

您可以使用Apache Commons Lang中的 ArrayUtils.contains

public static boolean contains(Object[] array, Object objectToFind)

请注意,如果传递的数组为null ,则此方法返回false

还有适用于各种原始数组的方法。

例:

 String[] fieldsToInclude = { "id", "name", "location" }; if ( ArrayUtils.contains( fieldsToInclude, "id" ) ) { // Do some stuff. } 

我很惊讶没有人建议只是简单地手工实现它:

 public static  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  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; } 

如果数组未排序,则必须迭代所有内容并在每个上调用equals。

如果数组已排序,您可以进行二进制搜索, Arrays类中有一个。

一般来说,如果要进行大量的成员资格检查,您可能希望将所有内容存储在Set中,而不是存储在数组中。

检查数组是否包含值的四种不同方法

1)使用List:

 public static boolean useList(String[] arr, String targetValue) { return Arrays.asList(arr).contains(targetValue); } 

2)使用Set:

 public static boolean useSet(String[] arr, String targetValue) { Set set = new HashSet(Arrays.asList(arr)); return set.contains(targetValue); } 

3)使用简单的循环:

 public static boolean useLoop(String[] arr, String targetValue) { for (String s: arr) { if (s.equals(targetValue)) return true; } return false; } 

4)使用Arrays.binarySearch():

下面的代码是错误的,这里列出的是完整性。 binarySearch()只能用于排序数组。 你会发现下面的结果很奇怪。 这是排序数组时的最佳选择。

 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 

为了它的价值,我进行了一项测试,比较了3个速度建议。 我生成了随机整数,将它们转换为String并将它们添加到数组中。 然后我搜索了最高可能的数字/字符串,这对于asList()。contains()来说是最糟糕的情况。

当使用10K数组大小时,结果在哪里:

排序和搜索:15
二进制搜索:0
 asList.contains:0

使用100Karrays时,结果如下:

排序和搜索:156
二进制搜索: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)); } } 

使用Java 8,您可以创建流并检查流中的任何条目是否与"s"匹配:

 String[] values = {"AB","BC","CD","AE"}; boolean sInArray = Arrays.stream(values).anyMatch("s"::equals); 

或者作为通用方法:

 public static  boolean arrayContains(T[] array, T value) { return Arrays.stream(array).anyMatch(value::equals); } 

您可以使用Arrays.asList方法以类似的方式直接将其初始化为List,而不是使用快速数组初始化语法,例如:

 public static final List STRINGS = Arrays.asList("firstString", "secondString" ...., "lastString"); 

然后你可以做(​​如上所述): STRINGS.contains("the string you want to find");

您可以使用Arrays类对值执行二进制搜索。 如果您的数组未排序,则必须使用同一类中的排序函数对数组进行排序,然后搜索它。

ObStupidAnswer(但我觉得这里有一个教训):

 enum Values { AB, BC, CD, AE } try { Values.valueOf(s); return true; } catch (IllegalArgumentException exc) { return false; } 

实际上,如果您使用HashSet,Tom Hawtin建议您不必担心排序,并且您的速度与预分类arrays上的二进制搜索相同,可能更快。

这一切都取决于代码的设置方式,显然,但从我的立场来看,订单将是:

在UNsorted数组上:

  1. HashSet的
  2. asList
  3. 排序和二进制

在排序的数组上:

  1. HashSet的
  2. 二进制
  3. asList

无论哪种方式,HashSet ftw

如果你有google集合库,可以使用ImmutableSet简化Tom的答案(http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/ImmutableSet.html)

这确实从提出的初始化中消除了很多混乱

 private static final Set VALUES = ImmutableSet.of("AB","BC","CD","AE"); 

一种可能的方案:

 import java.util.Arrays; import java.util.List; public class ArrayContainsElement { public static final List 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"); } } } 

开发人员经常这样做:

 Set set = new HashSet(Arrays.asList(arr)); return set.contains(targetValue); 

上面的代码可以工作,但是不需要先将列表转换为set。 将列表转换为集合需要额外的时间。 它可以很简单:

 Arrays.asList(arr).contains(targetValue); 

要么

  for(String s: arr){ if(s.equals(targetValue)) return true; } return false; 

第一个比第二个更可读。

Java 8中使用Streams。

 List myList = Arrays.asList("a1", "a2", "b1", "c2", "c1"); myList .stream() .filter(s -> s.startsWith("c")) .map(String::toUpperCase) .sorted() .forEach(System.out::println); 

使用简单的循环是最有效的方法。

 boolean useLoop(String[] arr, String targetValue) { for(String s: arr){ if(s.equals(targetValue)) return true; } return false; } 

由Programcreek提供

  1. 对于有限长度的arrays,使用以下(由camickr给出)。 这对于重复检查来说很慢,特别是对于较长的arrays(线性搜索)。

      Arrays.asList(...).contains(...) 
  2. 如果您反复检查更大的元素集,以获得快速性能

    • 数组是错误的结构。 使用TreeSet并将每个元素添加到它。 它对元素进行排序并具有快速exist()方法(二进制搜索)。

    • 如果元素实现Comparable您希望TreeSet排序:

      ElementClass.compareTo()方法必须与ElementClass.equals()兼容:看看Triads没有显示出战斗? (Java设置缺少一个项目)

       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)); 
    • 否则,请使用您自己的Comparator

       class MyComparator implements Comparator { 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); 

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. } 

使用Array.BinarySearch(array,obj)来查找数组中的给定对象。 例如:

if (Array.BinarySearch(str, i) > -1) – > true –exists

假 – 不存在

我很晚才加入这个讨论,但是由于我在解决这个问题的方法,几年前我遇到它时,与我在这里发布的其他答案有点不同,我发布了我当时使用的解决方案,在这里,如果有人发现它有用:( 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  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  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  boolean in(final T[] ts, final T t){ return indexOf(ts, t) > -1 ; } } 

正如您在上面的代码中看到的那样,还有其他实用程序方法ObjectUtils.equals()ArrayUtils.indexOf() ,它们也在其他地方使用过。

它可以很简单:

 String[] VALUE = new String[] {"AB","BC","CD","AE"}; Arrays.asList(VALUE).contains(s); 

检查一下

 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 } } 

尝试这个:

 ArrayList arrlist = new ArrayList(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"); } 

如果您不希望它区分大小写

 Arrays.stream(VALUES).anyMatch(s::equalsIgnoreCase); 

这是我使用util包中的Arrays类的简单代码。 它可以通过许多其他方式完成,但得到问题,这种方法首先出现在我的脑海中。

 String a[] = {"abc","xyz","pqr"}; System.out.println(Arrays.asList(a).contains("abc")); //will return true System.out.println(Arrays.asList(a).contains("abcd")); // will return false 

创建一个最初设置为false的布尔值。 运行循环以检查数组中的每个值,并与要检查的值进行比较。 如果你得到一个匹配,将boolean设置为true并停止循环。 然后声明布尔值为true。