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

2701

我有一个包含以下值的String[]

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

给定字符串 s,是否有一种好的方法来测试 VALUES 是否包含 s


6
可以使用 for 循环来解决,代码如下:"for (String s : VALUES) if (s.equals("MYVALUE")) return true;"。 - Zack
3
@camickr--我遇到了一个几乎相同的情况,链接是这个:https://dev59.com/A3VC5IYBdhLWcg3wpi98#223929。它一直得到投票,但只是从sun的文档中复制粘贴而来。我猜分数是基于你提供了多少帮助,而不是你付出了多少努力——大多数情况下是你多快发布答案!也许我们已经偶然发现了John Skeet的秘密!好的回答,+1给你。 - Bill K
3
如果你正在使用Apache Commons,那么org.apache.commons.lang.ArrayUtils.contains()可以为你完成这个任务。 - Mr. Boy
50
因为像我这样的人会在谷歌上搜索问题,点击 SO 的结果,看到你的答案,测试它,发现它有效,就会点赞该答案然后离开。 - Aequitas
2
我真的很想在java.util.Arrays中找到一个简单的indexOfcontains,它们都包含直接的循环。是的,你可以在1分钟内编写它们;但我仍然去了StackOverflow,期望在JDK的某个地方找到它们。 - tucuxi
显示剩余2条评论
32个回答

21

这是一个愚蠢的回答(但我认为其中有一些教训):

enum Values {
    AB, BC, CD, AE
}

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

2
抛出异常显然很耗费资源,但这是一种测试数值是否有效的新颖方式。缺点是枚举必须事先定义好。 - James P.

14

开发人员通常会做以下事情:

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;

第一个比第二个更易读。


14

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

显然,这完全取决于您的代码设置方式,但从我的角度来看,排序顺序应该是:

在一个未排序 的数组上:

  1. HashSet
  2. asList
  3. sort & binary

在已排序的数组上:

  1. HashSet
  2. Binary
  3. asList

因此,无论哪种方式,都应选择HashSet。


3
哈希集合的成员检查应该是O(1),而在排序集合上进行二分查找的时间复杂度是O(log n)。 - Skylar Saveland

11
如果你有Google Collections库,可以使用ImmutableSet(http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/ImmutableSet.html)来简化Tom的答案,这样可以大大减少所提议的初始化中的混乱。
private static final Set<String> VALUES =  ImmutableSet.of("AB","BC","CD","AE");

10

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

10

一个可能的解决方案:

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

6

最短的解决方案
数组 VALUES 可能包含重复项
自Java 9以来

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

Arrays.asList(VALUES).contains(s)通常比List.of(VALUES).contains(s)更具性能,因为它是对数组的视图,不需要将所有数组值复制到一次性列表中。 - M. Justin
正如@M.Justin所述: asList() 将原始数组 VALUES 包装为 List 接口。 List.of() 返回一个不可变列表,它是原始输入数组 VALUES 的副本。因此,原始列表可以更改而不会对返回列表产生任何影响。 - Kaplan

6
使用简单的循环是完成此操作最有效的方法。
boolean useLoop(String[] arr, String targetValue) {
    for(String s: arr){
        if(s.equals(targetValue))
            return true;
    }
    return false;
}

Courtesy to Programcreek


如果数组在目标值之前包含空引用,则会抛出空指针异常。 - Samuel Edwin Ward
1
if语句应该是:if (targetValue.equals(s)),因为String equals方法具有instanceof检查器。 - TheArchon
请使用Objects.equals(obj1,obj2)来确保空值安全。 - trilogy

6

请使用以下代码(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()也在其他地方使用过。


5
如果您不想区分大小写,可以这样做:
Arrays.stream(VALUES).anyMatch(s::equalsIgnoreCase);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接