Java:如何在hashmap中获得具有相同值的键集

Java:如何在hashmap中获得具有相同值的键集,java,hashmap,Java,Hashmap,我有一个hashmap,如下所示: 1->x 2->y 3->x 4->z 现在我想知道所有值为x(ans:[1,3])的键。最好的方法是什么 蛮力方法是在映射上迭代,并将值为x的所有键存储在数组中 有什么有效的方法吗 感谢hashmap是一种结构,它针对使用键的值的关联访问进行了优化,但与数组(例如)相反,它做得再好不过了。我不认为你能做得比迭代更好。提高效率的唯一方法是,如果您也有一个反向哈希映射(即哈希映射,其中您持有一个指向所有值的给定值的键数组)。是的,就是蛮力。您还可以通过存储“值-

我有一个hashmap,如下所示:

1->x

2->y

3->x

4->z

现在我想知道所有值为x(ans:[1,3])的键。最好的方法是什么

蛮力方法是在映射上迭代,并将值为x的所有键存储在数组中

有什么有效的方法吗


感谢

hashmap是一种结构,它针对使用键的值的关联访问进行了优化,但与数组(例如)相反,它做得再好不过了。我不认为你能做得比迭代更好。提高效率的唯一方法是,如果您也有一个反向哈希映射(即哈希映射,其中您持有一个指向所有值的给定值的键数组)。

是的,就是蛮力。您还可以通过存储“值->密钥集合”中的多重映射来加快更新速度,但要牺牲内存和更新的运行时成本。

如果您使用的是hashmap,则没有有效的方法,只能迭代值

hashmap
计算密钥的
hashcode()
,而不是值。除非你存储某种附加信息,或者考虑使用不同的数据结构,我认为你能得到的唯一方法就是蛮力。
如果您需要对值执行有效的操作,您应该考虑是否使用了适当的数据结构。

如果您愿意使用库,请使用,特别是
forMap()
结合
invertFrom()

您可以使用

Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "x");
map.put(2, "y");
map.put(2, "z");
map.put(3, "x");
map.put(4, "y");
map.put(5, "z");
map.put(6, "x");
map.put(7, "y");

System.out.println("Original map: " + map);

Multimap<String, Integer> multiMap = HashMultimap.create();
for (Entry<Integer, String> entry : map.entrySet()) {
  multiMap.put(entry.getValue(), entry.getKey());
}
System.out.println();

for (Entry<String, Collection<Integer>> entry : multiMap.asMap().entrySet()) {
  System.out.println("Original value: " + entry.getKey() + " was mapped to keys: "
      + entry.getValue());
}
根据noahz的建议,
forMap
invertFrom
占用的行数较少,但阅读起来可能更复杂:

HashMultimap<String, Integer> multiMap =
    Multimaps.invertFrom(Multimaps.forMap(map), 
        HashMultimap.<String, Integer> create());
HashMultimap multiMap=
多重映射。反转自(多重映射)。形式映射(映射),
HashMultimap.create());
代替:

Multimap<String, Integer> multiMap = HashMultimap.create();
for (Entry<Integer, String> entry : map.entrySet()) {
  multiMap.put(entry.getValue(), entry.getKey());
}
Multimap Multimap=HashMultimap.create();
for(条目:map.entrySet()){
multiMap.put(entry.getValue(),entry.getKey());
}

如果你已经有了一张地图,你应该考虑使用库来过滤你感兴趣的条目。您可以按照以下方式进行操作:

final Map<Integer, Character> filtered = Maps.filterValues(unfiltered, new Predicate<Character>() {
    @Override
    public boolean apply(Character ch) {
        return ch == 'x';
    }
});
final Map filtered=Maps.filterValues(未过滤,新谓词(){
@凌驾
公共布尔应用(字符ch){
返回ch=='x';
}
});

如果Java 8是一个选项,您可以尝试一种流媒体方法:

Map<Integer, String> map = new HashMap<>();
map.put(1, "x");
map.put(2, "y");
map.put(3, "x");
map.put(4, "z");

Map<String, ArrayList<Integer>> reverseMap = new HashMap<>(
    map.entrySet().stream()
        .collect(Collectors.groupingBy(Map.Entry::getValue)).values().stream()
        .collect(Collectors.toMap(
                item -> item.get(0).getValue(),
                item -> new ArrayList<>(
                    item.stream()
                        .map(Map.Entry::getKey)
                        .collect(Collectors.toList())
                ))
        ));

System.out.println(reverseMap);
如果首选Java 7:

Map<String, ArrayList<Integer>> reverseMap = new HashMap<>();

for (Map.Entry<Integer,String> entry : map.entrySet()) {
    if (!reverseMap.containsKey(entry.getValue())) {
        reverseMap.put(entry.getValue(), new ArrayList<>());
    }
    ArrayList<Integer> keys = reverseMap.get(entry.getValue());
    keys.add(entry.getKey());
    reverseMap.put(entry.getValue(), keys);
}
试试这个

public static void main(String[] args) {
        HashMap<String, String> hashMap = new HashMap<String, String>();
        hashMap.put("cust_tenure", "3_sigma");
        hashMap.put("cust_age", "3_sigma");
        hashMap.put("cust_amb_6m_sav", "3_sigma");
        hashMap.put("cust_amb_6m_chq", "3_sigma");
        hashMap.put("cust_total_prod_6m", "3_sigma");

        HashMap<String, ArrayList<String>> result = new LinkedHashMap<String, ArrayList<String>>();

        for (String key : hashMap.keySet()) {
            ArrayList<String> colName = null;
            if (!result.containsKey(hashMap.get(key))) {
                colName = new ArrayList<String>();
                colName.add(key);
                result.put(hashMap.get(key), colName);
            } else {
                colName = result.get(hashMap.get(key));
                colName.add(key);
                result.put(hashMap.get(key), colName);
            }

            System.out.println(key + "\t" + hashMap.get(key));
        }

        for (String key : result.keySet()) {
            System.out.println(key + "\t" + result.get(key));
        }

        System.out.println(hashMap.size());

    }
publicstaticvoidmain(字符串[]args){
HashMap HashMap=新的HashMap();
hashMap.put(“客户任期”、“3西格玛”);
hashMap.put(“客户年龄”、“3西格玛”);
hashMap.put(“cust_amb_6m_sav”,“3_sigma”);
hashMap.put(“cust_amb_6m_chq”,“3_sigma”);
hashMap.put(“客户总产量6m”、“3西格玛”);
HashMap结果=新建LinkedHashMap();
for(字符串键:hashMap.keySet()){
ArrayList colName=null;
if(!result.containsKey(hashMap.get(key))){
colName=newarraylist();
colName.add(key);
result.put(hashMap.get(key),colName);
}否则{
colName=result.get(hashMap.get(key));
colName.add(key);
result.put(hashMap.get(key),colName);
}
System.out.println(key+“\t”+hashMap.get(key));
}
for(字符串键:result.keySet()){
System.out.println(key+“\t”+result.get(key));
}
System.out.println(hashMap.size());
}

我同意George Campbell的观点,但对于java 8,我会做得简单一点:

Map<String, List<Integer>> reverseMap = map.entrySet()
    .stream()
    .collect(Collectors.groupingBy(Map.Entry::getValue,
        Collectors.mapping(
            Map.Entry::getKey,
            Collectors.toList())));
Map reverseMap=Map.entrySet()
.stream()
.collect(收集器.groupingBy(Map.Entry::getValue、,
图(
Map.Entry::getKey,
收藏家;

没错。如果只提供HashMap,任何其他实用程序也会进行迭代。或者…可能
Multimaps.forMap()
invertFrom()
结合使用时,它完全符合提问者的要求?很好的解决方案,我会记住这一点。如果您只需要特定值的键(这是OP要求的),这个解决方案是最好的;沿途无需创建两个
MultiMap
s。注意,您不必编写自己的谓词;只需使用
Maps.filterValues(未过滤的谓词.equalTo('x')).keySet()
。问题表明他“已经有了
HashMap
。因此
Multimaps.forMap()
invertFrom()
是一个更简洁的解决方案。不知道“更简洁”“考虑到这一点,它减少了一行,但我也更新了以反映您的答案。无法推断HashmapIt的给定错误的类型参数”无法推断Hashmap的类型参数“从技术上讲,这应该是一个
Collectors.toSet()
而不是
Collectors.toList()
              10,000,000        20,000,000
Java 7:         615 ms            11624 ms         
Java 8:        1579 ms             2176 ms
public static void main(String[] args) {
        HashMap<String, String> hashMap = new HashMap<String, String>();
        hashMap.put("cust_tenure", "3_sigma");
        hashMap.put("cust_age", "3_sigma");
        hashMap.put("cust_amb_6m_sav", "3_sigma");
        hashMap.put("cust_amb_6m_chq", "3_sigma");
        hashMap.put("cust_total_prod_6m", "3_sigma");

        HashMap<String, ArrayList<String>> result = new LinkedHashMap<String, ArrayList<String>>();

        for (String key : hashMap.keySet()) {
            ArrayList<String> colName = null;
            if (!result.containsKey(hashMap.get(key))) {
                colName = new ArrayList<String>();
                colName.add(key);
                result.put(hashMap.get(key), colName);
            } else {
                colName = result.get(hashMap.get(key));
                colName.add(key);
                result.put(hashMap.get(key), colName);
            }

            System.out.println(key + "\t" + hashMap.get(key));
        }

        for (String key : result.keySet()) {
            System.out.println(key + "\t" + result.get(key));
        }

        System.out.println(hashMap.size());

    }
Map<String, List<Integer>> reverseMap = map.entrySet()
    .stream()
    .collect(Collectors.groupingBy(Map.Entry::getValue,
        Collectors.mapping(
            Map.Entry::getKey,
            Collectors.toList())));