我如何testing一个数组是否包含某个值?
我有一个String[]
值如下所示:
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
鉴于String s
,有没有一种testingVALUES
是否包含s
的好方法?
Arrays.asList(yourArray).contains(yourValue)
警告:这不适用于基元数组(请参阅注释)。
由于java-8
您现在可以使用Stream
来检查int
, double
或long
数组是否包含值(分别使用IntStream
, DoubleStream
或LongStream
)
例
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<String> VALUES = new HashSet<String>(Arrays.asList( new String[] {"AB","BC","CD","AE"} ));
(偏执的人,比如我自己,如果这个包裹在Collections.unmodifiableSet
,可能会更放心 – 甚至可以公开。)
给定string,有没有一种testingVALUES是否包含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. }
我很惊讶没有人build议只是简单地实现它:
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
条件在方法内部是常量,在方法调用期间总是计算为相同的布尔值。 因此,如果inputarray
很大,则只需评估一次该条件就可以更有效,并且可以基于结果在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; }
如果数组没有sorting,则必须遍历所有内容,并在每个数组上调用equals。
如果数组已sorting,则可以执行二分search,在Arrays类中有一个。
一般来说,如果您要进行大量的会员检查,您可能希望将所有内容存储在Set中,而不是数组中。
四种不同的方法来检查一个数组是否包含一个值
1)使用列表:
public static boolean useList(String[] arr, String targetValue) { return Arrays.asList(arr).contains(targetValue); }
2)使用设置:
public static boolean useSet(String[] arr, String targetValue) { Set<String> set = new HashSet<String>(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()只能用于已sorting的数组。 你会发现下面的结果是奇怪的。 数组sorting后,这是最好的select。
public static boolean binarySearch(String[] arr, String targetValue) { int a = Arrays.binarySearch(arr, targetValue); if (a > 0) return true; else return false; }
快速示例:
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
对于它的价值,我跑了一个testing比较速度的3个build议。 我生成随机整数,将它们转换为一个string,并将它们添加到数组。 然后我search了可能的最高数字/string,这对asList()。contains()来说是最坏的情况。
当使用10Karrays尺寸时,结果如下:
sorting和search:15 二进制search:0 asList.contains:0
使用100Karrays时,结果如下:
sorting和search:156 二进制search:0 asList.contains:32
所以如果按照sorting顺序创build数组,那么二分search是最快的,否则asList()。contains就是要走的路。 如果你有很多search,那么sorting数组可能是值得的,所以你可以使用二进制search。 这一切都取决于你的应用程序。
我想这些是大多数人所期望的结果。 这里是testing代码:
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)); } }
而不是使用快速数组初始化语法,您可以使用Arrays.asList方法以类似方式直接将其初始化为List,例如:
public static final List<String> STRINGS = Arrays.asList("firstString", "secondString" ...., "lastString");
然后你可以做(像上面): STRINGS.contains("the string you want to find");
在Java 8中,您可以创build一个stream并检查stream中的任何条目是否匹配"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); }
您可以使用Arrays类来执行值的二进制search。 如果你的数组没有sorting,你将不得不使用同一个类中的sorting函数来sorting数组,然后search它。
ObStupidAnswer(但我认为这里有一个教训在这里的某个地方):
enum Values { AB, BC, CD, AE } try { Values.valueOf(s); return true; } catch (IllegalArgumentException exc) { return false; }
实际上,如果你使用HashSet,Tom Hawtinbuild议你不必担心sorting,你的速度和预分类数组上的二进制search一样,可能更快。
这一切都取决于你的代码是如何设置的,但是从我的立场来看,顺序是:
在UNsorted数组上:
- HashSet的
- asList
- sorting和二进制
在一个sorting的数组上:
- HashSet的
- 二进制
- asList
所以无论如何,HashSet ftw
如果你有谷歌collections库,汤姆的答案可以通过使用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");
在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);
使用简单的循环是最有效的方法。
boolean useLoop(String[] arr, String targetValue) { for(String s: arr){ if(s.equals(targetValue)) return true; } return false; }
礼貌对Programcreek
开发人员经常这样做:
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;
第一个比第二个更可读。
-
对于有限长度的数组,使用以下(由camickr给出)。 对于重复检查来说这很慢,特别是对于较长的数组(线性search)。
Arrays.asList(...).contains(...)
-
如果您反复检查更大的一组元素,可以获得更快的性能
-
数组是错误的结构。 使用
TreeSet
并添加每个元素。 它sorting元素,并有一个快速的exist()
方法(二进制search)。 -
如果元素实现了
Comparable
,并且您希望TreeSet
进行sorting:ElementClass.compareTo()
方法必须与ElementClass.equals()
兼容:请参阅黑社会没有显示的战斗? (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<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);
-
Arrays.asList =>然后应用contains()方法将始终工作,但是searchalgorithm要好得多,因为首先必须将数组转换为列表,然后调用contains方法,使开销增加一倍,查看我的意思? 这是因为它是O(n)创build列表和O(n)为包含通过顺序检查find一个元素。 当一个简单的线性search只做一次工作时,为什么要遭受O(n)两次。
public boolean findString(String[] strings, String desired){ for(String s : strings){ if (desired.equals(s)){ 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 – 存在
假 – 不存在
尝试这个:
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"); }
我join这个讨论的时间已经很晚了,但是自从我几年前面对这个问题的时候,我的方法和之前已经发表的其他答案有所不同,所以我发布了当时使用的解决scheme,在这里,如果有人发现它有用:(在此代码中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()
,这些方法也在其他地方使用。
一个可能的解决scheme是:
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"); } } }
检查这个
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 } }
谢谢
它可以像下面这样简单:
String[] VALUE = new String[] {"AB","BC","CD","AE"}; Arrays.asList(VALUE).contains(s);