我有一个 String[]
像这样的值:
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
特定 String s
,有没有一种好的方法来测试是否 VALUES
包含 s
?
我有一个 String[]
像这样的值:
public static final String[] VALUES = new String[] {"AB","BC","CD","AE"};
特定 String s
,有没有一种好的方法来测试是否 VALUES
包含 s
?
Arrays.asList(yourArray).contains(yourValue)
警告:这不适用于基元数组(请参阅注释)。
你现在可以使用了 Stream
检查是否有数组 int
, double
要么 long
包含一个值(分别使用a 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,有没有一种很好的方法来测试VALUES是否包含s?”
VALUES.contains(s)
O(1)。
您可以使用 ArrayUtils.contains
从 Apache Commons Lang
public static boolean contains(Object[] array, Object objectToFind)
请注意,此方法返回 false
如果传递的数组是 null
。
还有适用于各种原始数组的方法。
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
condition在方法内是常量,它总是在方法调用期间计算为相同的布尔值。所以如果输入 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;
}
如果数组未排序,则必须迭代所有内容并在每个上调用equals。
如果数组已排序,您可以进行二进制搜索,其中有一个 数组 类。
一般来说,如果要进行大量的成员资格检查,您可能希望将所有内容存储在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<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) {
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
使用100K阵列时,结果如下:
排序和搜索: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));
}
}