将 Map<String, List<String>> 输入分配给 Map<String, List<String>> 输出

Assign Map<String, List<String>> input to Map<String, List<String>> output

我是 Streams 的新手,我想要这样的东西: 我有一个带有 <String, List<String>> 的输入地图。我想在流中读取此映射并将其分配给具有 <String, String> 的输出映射,其值是输入映射中值列表的第一个元素。 示例:

**Input:**
{key1, [value1 value2]}
{key2, null}

**Output**
{key1, value1}
{key2, null}

注意,当第一个map中的list为null时,那么在第二个map中应该写为null。如果list为空,那么第二个map值也应​​该写null

我尝试过的:

Map<String, String> output= input.entrySet().stream()
                    .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().get(0)));

当第一个地图中的列表为空时,这会给出 java.lang.NullPointerException

不幸的是,如果你输入 null 值,Collectors.toMap 也会 抛出。

要解决此问题,您可以为 Map 内联构建 Collector。例如,类似于:

final Map<String, String> output = input.entrySet().stream()
        .collect(HashMap::new, // Create a Map if none is present
                (map, entry) -> map.put(entry.getKey(), // Keys stay the same
                (entry.getValue() == null || entry.getValue().isEmpty()) // Check for empty
                    ? null : entry.getValue().iterator().next()), // Get first if present
                HashMap::putAll); // Combining function

注意:用 Collections.unmodifiableMap 包裹它可以避免将来被污染。 注意:将 'get first value or null' 提取到如下方法可能更具可读性,并允许组合位在上述管道中变为 this.getFirstIfPresent(entry.getValue())

private static <T> @Nullable T getFirstIfPresent(final List<T> input) {
    if (list == null || list.isEmpty()) {
        return null;
    }

    return list.iterator().next();
}