如何确定数组是否包含Java中的特定值?

我有一个String[],其值如下:

public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};

给定String s,是否有一个好的方法来测试VALUES是否包含s

2527685 次浏览
Arrays.asList(yourArray).contains(yourValue)

警告:这不适用于原语数组(请参阅注释)。


开始,您现在可以使用Streams。

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

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

示例

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

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

如果数组没有排序,您将不得不遍历所有内容并对每个数组调用equals。

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

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

JavaSE 9的简明更新

引用数组不好。对于这种情况,我们在一个集合之后。从JavaSE 9开始,我们有Set.of

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

“给定String 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可以预见仍然缺少不可变的集合类型,并且语法仍然过于冗长,不适合我的口味。)

ObStupid答案(但我认为这里有一个教训):

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

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

当使用10K数组大小时,结果是:

Sort & Search   : 15Binary Search   : 0asList.contains : 0

当使用100K数组时,结果是:

Sort & Search   : 156Binary Search   : 0asList.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));}}

实际上,如果你像Tom Hawtin建议的那样使用HashSet,你就不需要担心排序问题,而且你的速度与预先排序的数组上的二进制搜索相同,甚至可能更快。

显然,这完全取决于你的代码是如何设置的,但从我的立场来看,顺序是:

未排序数组上:

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

在排序数组上:

  1. HashSet
  2. 二进制
  3. asList

所以不管怎样,HashSet都是为了胜利。

而不是使用快速数组初始化语法,你可以直接初始化为一个列表以类似的方式使用Arrays.as列表方法,例如:

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)

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

也有可用于各种原始数组的方法。

示例:

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

如果你有谷歌收藏库,汤姆的答案可以通过使用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;}
  1. 对于长度有限的数组,请使用以下内容(如camickr所示)。这对于重复检查来说很慢,尤其是对于较长的数组(线性搜索)。

     Arrays.asList(...).contains(...)
  2. For fast performance if you repeatedly check against a larger set of elements

    • An array is the wrong structure. Use a TreeSet and add each element to it. It sorts elements and has a fast exist() method (binary search).

    • If the elements implement Comparable & you want the TreeSet sorted accordingly:

      ElementClass.compareTo() method must be compatable with ElementClass.equals(): see Triads not showing up to fight? (Java Set missing an item)

      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));
    • Otherwise, use your own 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 comparatorTreeSet myElements = new TreeSet(new MyComparator());
      // Do this for each element (implementing *Comparable*)myElements.add(nextElement);
    • The payoff: check existence of some element:

      // Fast binary search through sorted elements (performance ~ log(size)):boolean containsElement = myElements.exists(someElement);

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

示例:

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

false--不存在

试试这个:

ArrayList<Integer> arrlist = new ArrayList<Integer>(8);
// use add() method to add elements in the listarrlist.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");}

使用Java8,您可以创建一个流并检查流中的任何条目是否匹配"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);}

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

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

礼貌Programcreek

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

  1. 使用List

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

    public static boolean useSet(String[] arr, String targetValue) {Set<String> set = new HashSet<String>(Arrays.asList(arr));return set.contains(targetValue);}
  3. Using a simple loop:

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

    The code below is wrong, it is listed here for completeness. binarySearch() can ONLY be used on sorted arrays. You will find the result is weird below. This is the best option when array is sorted.

    public static boolean binarySearch(String[] arr, String targetValue) {return Arrays.binarySearch(arr, targetValue) >= 0;}

Quick Example:

String testValue="test";String newValueNotInList="newValue";String[] valueArray = { "this", "is", "java" , "test" };Arrays.asList(valueArray).contains(testValue); // returns trueArrays.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}}

开发人员经常这样做:

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");}}}

Java8中使用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()->,然后调用包含()方法将始终有效,但搜索算法要好得多,因为您不需要在数组周围创建轻量级列表包装器,这就是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的布尔值。运行一个循环来检查数组中的每个值并与您要检查的值进行比较。如果您得到匹配,请将布尔值设置为true并停止循环。然后断言布尔值为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));}

尝试使用Java8谓词测试方法

这里有一个完整的例子。

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时,到目前为止我得到的最好的是从字节数-javahttps://github.com/patrickfav/bytes-java看起来是一件很好的工作

最短的解决方案
该阵列VALUES可能包含重复
Java9

List.of(VALUES).contains(s);

我发现这个解决方案非常简单和有效。

在我的情况下,它是关于一个简单的拖放应用程序,但适用于任何东西:

超文本标记语言:

<span id="drag1" data-div='["drop1", "drop6"]' draggable="true" ondragstart="drag(event)"><b>&emsp;Whatever you want to drag&emsp;</b></span></div>

这里的关键是data-div='["drop1","drop6"]',即数组。

JAVASCRIPT:

function allowDrop(ev) {ev.preventDefault();}
function drag(ev) {ev.dataTransfer.setData("text", ev.target.id);}
function drop(ev) {ev.preventDefault();var data = ev.dataTransfer.getData("text");  
if (document.getElementById(data).getAttribute('data-div').includes(ev.target.id)) {alert("That is correct!");ev.target.appendChild(document.getElementById(data));}else {alert("That association is wrong. Try again!");}
}

这里的键是.包括(ev.target.id),它只检查特定项是否在数组中。

我在https://www.samanthaming.com/tidbits/81-how-to-check-if-array-includes-a-value/找到的

希望有帮助。