繁体   English   中英

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

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


您现在可以使用 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);

Java SE 9 的简明更新

引用数组不好。 对于这种情况,我们需要一组。 从 Java SE 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 仍然缺少不可变的集合类型,而且语法仍然过于冗长,以我的口味。)

您可以使用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 <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. 使用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<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()只能用于排序数组。 你会发现下面的结果很奇怪。 这是排序数组时的最佳选择。

     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

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

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

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

值得一提的是,我进行了一项测试,比较了 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));
    }
}

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

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

然后你可以做(​​如上):

STRINGS.contains("the string you want to find");

使用 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);
}

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

ObStupidAnswer(但我认为这里有一个教训):

enum Values {
    AB, BC, CD, AE
}

try {
    Values.valueOf(s);
    return true;
} catch (IllegalArgumentException exc) {
    return false;
}

实际上,如果您像 Tom Hawtin 建议的那样使用 HashSet<String> ,则无需担心排序,并且您的速度与对预排序数组进行二分搜索的速度相同,甚至可能更快。

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

未排序的数组上:

  1. 哈希集
  2. 列表
  3. 排序和二进制

在排序数组上:

  1. 哈希集
  2. 二进制
  3. 列表

所以无论哪种方式,HashSet 都是胜利的。

如果你有谷歌收藏库,汤姆的答案可以通过使用 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");

一种可能的解决方案:

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

开发人员经常这样做:

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;

第一个比第二个更具可读性。

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

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

感谢Programcreek

Java 8 中使用流。

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);
  1. 对于长度有限的数组,请使用以下内容(由camickr给出)。 这对于重复检查很慢,尤其是对于较长的数组(线性搜索)。

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

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

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

      ElementClass.compareTo()方法必须与ElementClass.equals()兼容:看到Triads 没有出现战斗吗? (Java Set 缺少一个项目)

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

使用以下内容(此代码中的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() ,它们也在其他地方使用过。

尝试这个:

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

检查这个

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

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

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

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

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

例子:

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

false -- 不存在

最短的解决方案
数组VALUES可能包含重复项
从 Java 9 开始

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

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

尝试使用 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

当我使用原始类型字节和字节 [] 处理低级 Java 时,到目前为止我得到的最好的是来自bytes-java https://github.com/patrickfav/bytes-java似乎是一件很好的工作

在下面使用 -

    String[] values = {"AB","BC","CD","AE"};
    String s = "A";
    boolean contains = Arrays.stream(values).anyMatch(v -> v.contains(s));

使用 Spliterator 可防止不必要地生成 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如果search包含在数组中


确实适用于原始数组

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 );
…

您可以通过两种方法进行检查

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

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

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

HTML:

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

}

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

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

希望能帮助到你。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM