当前位置: 首页 > 知识库问答 >
问题:

如何测试数组是否包含映射中的每个值?

孙昂然
2023-03-14

我有一张地图:

Map<String, String> abc = new HashMap<>();

"key 1":"价值1",
"key 2":"价值2"

以及一个数组:

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

共有3个答案

东郭昌胤
2023-03-14

我建议使用流:

final List<String> optionsList = Arrays.asList(options);
abc.values().stream().allMatch(optionsList::contains);
孙海
2023-03-14

可以使用https://docs . Oracle . com/javase/7/docs/API/Java/util/list . html # contains all(Java . util . collection)

Arrays.asList("value1", "value2", "value3").containsAll(abc.values())
雍阳
2023-03-14

您当前的方法创建了一个<code>ArrayList</code>(来自<code>java.util.Arrays</code>,不要与<code>java.util</code>中的常规ArrayList混淆)来包装给定的数组。

然后,对于map的每个值,您调用ArrayList#包含方法。然而,这种方法非常慢。它遍历整个列表以搜索某些内容。

因此,您当前的方法会产生O(n^2),这不能很好地扩展。

我们可以通过使用专为快速包含查询而设计的数据结构(即 HashSet)来做得更好。

因此,我们不会将所有值放入ArrayList,而是将它们放入HashSet,其包含方法速度很快:

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()。大小()那么你可以直接返回false

您还可以使用Java 8和Streams来简化上述代码,其结果和幕后过程是相同的:

HashSet<String> valuesFromArray = new HashSet<>(Arrays.asList(options));
boolean doesContainAll = abc.values().stream()
    .allMatch(valuesFromArray::contains);

让我们仔细看看< code > Java . util . arrays . ArrayList 。你可以在这里找到它的代码。

以下是包含方法的代码:

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)中运行。

如果您的任何一个数据可能包含重复项,并且您计划单独计数它们,那么您将需要一种稍微不同的方法,因为包含不会为重复项的数量而烦恼。

为此,您可以先将abc.values()收集到List中。然后,每次检查一个元素时,您都将从List中删除匹配的元素。

或者,您可以设置HashMap

 类似资料:
  • 如何检查数组中的所有元素是否相同? 这是我想到的唯一解决办法。我想知道有没有有效的?

  • 我实际上有两种类型的数据: 我想用Hamcrest在我的身体响应中测试我的放心请求后,b(元素接收)是否包含来自a的一个或多个元素(

  • 问题内容: 如何测试字符串以查看其是否包含数组中的任何字符串? 而不是使用 问题答案: 编辑:这是使用Java 8流API的更新。如此清洁。仍然可以与正则表达式结合使用。 另外,如果我们将输入类型更改为List而不是数组,则可以使用。 如果希望返回匹配的字符串,也可以使用。 原始的过时的答案: 这是(VERY BASIC)静态方法。请注意,在比较字符串上区分大小写。一个原始的,使其不区分大小写的办

  • 问题内容: 找出JavaScript数组是否包含值的最简洁,最有效的方法是什么? 这是我知道的唯一方法: 有没有更好,更简洁的方法来实现这一目标? 这与Stack Overflow问题密切相关。在JavaScript数组中查找项目的最佳方法?解决使用数组查找对象的问题indexOf。 问题答案: 现代的浏览器,这不正是这一点,得到广泛支持的人,除IE: 你也可以使用,它不太直接,但对于过时的浏览器

  • 问题内容: 找出JavaScript数组是否包含值的最简洁,最有效的方法是什么? 这是我知道的唯一方法: 有没有更好,更简洁的方法来实现这一目标? 这与Stack Overflow问题密切相关。 在JavaScript数组中查找项目的最佳方法?解决使用数组查找对象的问题。 问题答案: 现代的浏览器,这不正是这一点,得到广泛支持的人,除IE: 你也可以使用,它不太直接,但对于过时的浏览器不需要使用。

  • 问题内容: 如何测试一个列表是否包含另一个列表(即它是一个连续的子序列)。假设有一个名为contains的函数: 编辑: 问题答案: 这是我的版本: 正如安德鲁·贾菲(Andrew Jaffe)在他的评论中指出的那样,它返回一个元组(start,end + 1),因为我认为这更像pythonic。它不对任何子列表进行切片,因此应该相当有效。 新手感兴趣的一点是,它使用了for语句上的else子句-