我有一张地图:
Map<String, String> abc = new HashMap<>();
&#34; KEY1&#34; :&#34; value1&#34;,
&#34; KEY2&#34; :&#34; value2&#34;
一个数组:
String[] options= {"value1", "value2", "value3"}
我正在创建这个数组如下(我正在使用以下方法做一些与我在这里问的问题无关的其他方法):
public String[] getOptions() {
List<String> optionsList = getOptionsFromAMethod(WebElementA);
String[] options = new String[optionsList.size()];
options = optionsList.toArray(options);
return options;
}
验证String []是否包含Map中的每个值的最佳方法是什么?
我正在考虑这样做:
for (Object value : abc.values()) {
Arrays.asList(options).contains(value);
}
答案 0 :(得分:2)
您当前的方法会创建一个ArrayList
(来自java.util.Arrays
,而不是与来自java.util
的常规ArrayList混淆)包装给定的数组
然后,为地图的每个值调用ArrayList#contains
方法。但是这种方法非常慢。它遍历整个列表以搜索某些内容。
因此,您当前的方法产生的O(n^2)
不能很好地扩展。
我们可以通过使用专为快速contains
查询设计的数据结构做得更好,即HashSet
。
因此,我们不会将所有值都放入ArrayList
,而是将HashSet
方法快速:{/ 1>
contains
代码现在可以在boolean doesContainAll = true;
HashSet<String> valuesFromArray = new HashSet<>(Arrays.asList(options));
for (String value : abc.values()) {
if (!valuesFromArray.contains(value)) {
doesContainAll = false;
break;
}
}
// doesContainAll now is correctly set to 'true' or 'false'
中使用,在复杂性方面更好,最佳。
当然,您可以通过常数因素进一步优化以加速。例如,您可以先检查尺寸,如果O(n)
大于options.length
,那么您可以直接返回abc.values().size()
。
你也可以使用 Java 8 和false
来简化上面的代码,结果以及幕后的程序是一样的:
Stream
让我们仔细研究HashSet<String> valuesFromArray = new HashSet<>(Arrays.asList(options));
boolean doesContainAll = abc.values().stream()
.allMatch(valuesFromArray::contains);
。您可以找到它的代码here。
以下是java.util.Arrays.ArrayList
方法的代码:
contains
让我们看看如何实施public boolean contains(Object o) {
return indexOf(o) != -1;
}
:
indexOf
实际上,在所有情况下,该方法都将通过源数组从左到右遍历以查找对象。 没有花哨的方法能够直接访问信息是否 对象,它在public int indexOf(Object o) {
E[] a = this.a;
if (o == null) {
for (int i = 0; i < a.length; i++)
if (a[i] == null)
return i;
} else {
for (int i = 0; i < a.length; i++)
if (o.equals(a[i]))
return i;
}
return -1;
}
而不在O(n)
中运行。
如果您的任何一个数据可能包含重复项并且您计划单独计算,那么您将需要稍微不同的方法,因为O(1)
不会打扰对于重复数量。
为此,您可以先将contains
收集到abc.values()
中。然后,每次检查元素时,都会从List
中删除匹配的元素。
或者,您可以设置一个List
来计算其出现的每个元素。然后,每次检查一个元素时,将计数器减一。
答案 1 :(得分:1)
您可以使用https://docs.oracle.com/javase/7/docs/api/java/util/List.html#containsAll(java.util.Collection)
Arrays.asList("value1", "value2", "value3").containsAll(abc.values())
答案 2 :(得分:0)
我建议使用一个流:
final List<String> optionsList = Arrays.asList(options);
abc.values().stream().allMatch(optionsList::contains);