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

我有一个hashmap如下:

1-> X

2->ÿ

3-> X

4->ž

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

蛮力方式是迭代地图并将所有键存储在值为x的数组中。

有没有有效的方法。

谢谢

您可以使用MultiMap轻松获取所有这些重复值。

 Map map = new HashMap(); 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 multiMap = HashMultimap.create(); for (Entry entry : map.entrySet()) { multiMap.put(entry.getValue(), entry.getKey()); } System.out.println(); for (Entry> entry : multiMap.asMap().entrySet()) { System.out.println("Original value: " + entry.getKey() + " was mapped to keys: " + entry.getValue()); } 

打印出来:

 Original map: {1=x, 2=z, 3=x, 4=y, 5=z, 6=x, 7=y} Original value: z was mapped to keys: [2, 5] Original value: y was mapped to keys: [4, 7] Original value: x was mapped to keys: [1, 3, 6] 

按照@ noahz的建议, forMapinvertFrom占用的行数较少,但可以说读起来更复杂:

 HashMultimap multiMap = Multimaps.invertFrom(Multimaps.forMap(map), HashMultimap. create()); 

取代:

 Multimap multiMap = HashMultimap.create(); for (Entry entry : map.entrySet()) { multiMap.put(entry.getValue(), entry.getKey()); } 

散列映射是一种优化的结构,用于使用键对值进行关联访问,但在执行反向操作时却没有比使用数组更好的结构。 我不认为你可以做得更好,然后迭代。 提高效率的唯一方法是,如果您也有反向哈希映射(即哈希映射,其中您持有指向所有值的给定值的键数组)。

如果Java 8是一个选项,您可以尝试流式处理方法:

 Map map = new HashMap<>(); map.put(1, "x"); map.put(2, "y"); map.put(3, "x"); map.put(4, "z"); Map> 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); 

结果如下:

 {x=[1, 3], y=[2], z=[4]} 

如果首选Java 7:

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

有趣的是,我在执行(索引,随机(’a’ – ‘z’)对的大型映射时,尝试了每种算法所需的时间。

  10,000,000 20,000,000 Java 7: 615 ms 11624 ms Java 8: 1579 ms 2176 ms 

如果您愿意使用库,请使用Google Guava的Multimaps实用程序 ,特别是forMap()invertFrom()相结合

是的,只是蛮力。 您还可以通过存储Value – > Key of Key的Multimap来加快速度,但代价是更新的内存和运行时成本。

HashMap计算键的hashcode() ,而不是值。 除非您存储某种附加信息,或考虑使用不同的数据结构,否则我认为唯一可以获得此信息的方法就是蛮力。

如果需要对值执行高效操作,则应考虑是否使用了适当的数据结构。

如果您使用的是散列映射,那么除了迭代值之外没有有效的方法

如果您已有地图,则应考虑使用Google的Guava库来过滤您感兴趣的条目。您可以执行以下操作:

 final Map filtered = Maps.filterValues(unfiltered, new Predicate() { @Override public boolean apply(Character ch) { return ch == 'x'; } }); 

我同意George Campbell但是对于java 8我会更容易做到:

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

尝试这个…..

 public static void main(String[] args) { HashMap hashMap = new HashMap(); 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> result = new LinkedHashMap>(); for (String key : hashMap.keySet()) { ArrayList colName = null; if (!result.containsKey(hashMap.get(key))) { colName = new ArrayList(); 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()); }