如何合并哈希映射中存在的重复值及其键


HashMap<String, String> map = new HashMap<String, String>();
HashMap<String, String> newMap = new HashMap<String, String>();
map.put("A","1");
map.put("B","2");
map.put("C","2");
map.put("D","1");

预期输出:"AD"、"1"和"BC"、"2"存在于 newMap 中,这意味着,如果数据值相同,则需要通过在 newMap 中创建的组合其键来组合其键以只有一个数据值 如何在 Java 中实现这一点?

您希望使用Collectors.groupingBy按"整数"值分组,并将以前的键收集为新值。默认情况下,分组产生List。您可以进一步使用下游收集器Collectors.mapping和另一个下游收集器Collectors.reducing将各个项目(值)映射和连接为单个字符串。

Map<String, String> groupedMap = map.entrySet().stream()
.collect(Collectors.groupingBy(
Map.Entry::getValue,
Collectors.mapping(
Map.Entry::getKey,
Collectors.reducing("", (l, r) -> l + r))));
{1=AD, 2=BC}

现在,您可以使用最终结果的值切换键,尽管我真的认为您最终需要groupedMap中已有的内容,因为进一步处理可能会导致重复键出错:

Map<String, String> newMap = groupedMap.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getValue, 
Map.Entry::getKey));
{BC=2, AD=1}

可以,使用Collectors.collectingAndThen(口味问题)将它们放在一起:

Map<String, String> newMap = map.entrySet().stream()
.collect(Collectors.collectingAndThen(
Collectors.groupingBy(
Map.Entry::getValue,
Collectors.mapping(
Map.Entry::getKey,
Collectors.reducing("", (l, r) -> l + r))),
m -> m.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getValue, 
Map.Entry::getKey))));

基于逻辑:

  1. 循环浏览地图

  2. 对于每个值,从新映射中获取相应的键(基于值)

  3. 如果新的映射键存在,请将其删除,然后在末尾加上额外的字母重新放置

  4. 如果不存在,则不带任何串联即可放置它。

    for (var entry : map.entrySet()) 
    {
    String newMapKey = getKey(newMap, entry.getValue());
    if (newMapKey != null) 
    {
    newMap.remove(newMapKey);
    newMap.put(newMapKey + entry.getKey(), entry.getValue());
    continue;
    }
    newMap.put(entry.getKey(), entry.getValue());
    }
    

额外的方法:

private static String getKey(HashMap<String, String> map, String value) 
{
for (String key : map.keySet())
if (value.equals(map.get(key)))
return key;
return null;
}

{BC=2, AD=1}

使用 Java 8

您可以尝试以下方法以获得所需的结果。

法典:

public class Test {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<>();
Map<String, String> newMap;
map.put("A","1");
map.put("B","2");
map.put("C","2");
map.put("D","1");
Map<String, String> tempMap = map.entrySet().stream()
.collect(Collectors.groupingBy(Map.Entry::getValue,
Collectors.mapping(Map.Entry::getKey,Collectors.joining(""))));
newMap = tempMap.entrySet().stream().sorted(Map.Entry.comparingByValue())
.collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey,(a,b) -> a, LinkedHashMap::new));
System.out.println(newMap);
}
}

输出:

{AD=1, BC=2}

如果您希望源映射的按字母顺序连接,如示例"AD""BC"(而不是"DA""CB"),那么您可以通过创建类型为Map<String,List<String>>的中间映射并将源映射中的每个不同值与List相关联来确保这一点。然后对每个列表进行排序并从中生成一个字符串。

那如何实现:

Map<String, String> map = Map.of(
"A", "1", "B", "2","C", "2","D", "1"
);

Map<String, String> newMap = map.entrySet().stream()
.collect(Collectors.groupingBy( // intermediate Map<String, List<String>>
Map.Entry::getValue,
Collectors.mapping(Map.Entry::getKey, Collectors.toList())
))
.entrySet().stream()
.collect(Collectors.toMap(
e -> e.getValue().stream().sorted().collect(Collectors.joining()),
Map.Entry::getKey
));

newMap.forEach((k, v) -> System.out.println(k + " -> " + v));

输出:

BC -> 2
AD -> 1

最新更新