Java 流正在抛出 java.lang.IllegalStateException:重复键

Java streams is throwing java.lang.IllegalStateException: Duplicate key

我对 Java 流有点陌生,并且遇到了以下问题。我尝试了本网站和各种文章中提到的许多事情,但无法解决问题,因此请在此处发布问题。

我正在我的应用程序中使用 JavaStreams 创建一个 Map<String, Object> 然后我将值传递给 Map 和重复的 keys 然后它抛出以下错误:

java.lang.IllegalStateException: Duplicate key namespace:localName (attempted merging values [ONE] and [TWO])

    at java.base/java.util.stream.Collectors.duplicateKeyException(Collectors.java:133)

以下是引发此错误的方法:

public Map<String, Object> toMap() {
    final Map<String, Object> map = new HashMap<>();
    if (complex != null && complex.size() > 0) {
        final Map<String, Object> complexMap = complex.stream()
                .flatMap(c -> c.toMap().entrySet().stream())
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        map.put(namespacePrefix.concat(":").concat(localName), complexMap);
    } else {
        map.put(namespacePrefix.concat(":").concat(localName), text);
    }
    return map;
}

我尝试将 Object 设为 List,这样如果发现重复值,则将其添加到 List,如下所示:

List<Object> values = (List<Object>) map.get(namespacePrefix.concat(":").concat(localName));
if (values == null) {
    values = new ArrayList<Object>();
}
values.add(text);
map.put(namespacePrefix.concat(":").concat(localName), values);

但这似乎也不适合我。如果键重复,我想保留这两个值,因为我需要我的应用程序中的所有值。有人可以向我解释我在这里做错了什么以及如何解决它的一些想法吗?

这是有问题的行:

final Map<String, Object> complexMap = complex.stream().flatMap(c -> c.toMap().entrySet().stream()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

错误告诉您 complex 中至少有一些地图有共同的键。

您要么需要使用 Collectors.groupingBy,它会为每个键生成一个项目列表:

final Map<String, List<Object>> complexMap = complex.stream().flatMap(c -> c.toMap().entrySet().stream()).collect(Collectors.groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue, Collectors.toList())));

或使用 the overload of Collectors.toMap which takes a merging function,允许您指定应如何处理重复的键。

不允许使用 Collectors.toMap(Function, Function) 方法重复:

If the mapped keys contains duplicates (according to Object.equals(Object)), an IllegalStateException is thrown.

现在取决于您喜欢什么输出:

  • Map<String, Object>

    您需要将 Collectors.toMap(Function, Function, BinaryOperator) 与合并函数一起使用,该合并函数决定出现相同键时应使用哪个值。

    If the mapped keys contains duplicates (according to Object.equals(Object)), the value mapping function is applied to each equal element, and the results are merged using the provided merging function.

    此解决方案需要知道如何处理两个或多个重复的密钥。

  • Map<String, List<Object>>

    您需要使用分组收集器 Collectors.groupingBy(Function) 通过一个键对所有值进行分组,即以前的值作为值出现在 List 中。如果之前的键重复,新的 Map 将出现一次,而作为值的 List 将具有多个元素。

    Returns a Collector implementing a "group by" operation on input elements of type T, grouping elements according to a classification function, and returning the results in a Map.

    此解决方案为您添加了一个选项来识别重复的字段并稍后决定如何处理这些值。