繁体   English   中英

高效的方法是使用少量映射到相同值的键来反转哈希图

[英]Efficient way invert to invert a hashmap with a small number of the keys mapping to same values

我有一个哈希图,我知道有些键映射到相同的值。
这些键的数量非常小(小于6%),并且它们映射在2-4个值之间。
例如

Map<String, String> map = new HashMap<>();  
map.put("codeA", "100");  
map.put("codeB", "7");  
map.put("codeC", "0012");   

我需要从值到键创建此映射的逆,所以我这样做了:

inverseMap = new HashMap<String, ArrayList<String>>();
for(Map.Entry<String, String> e:map.entrySet()) {
    String code = e.getKey();
    String val = e.getValue();
    ArrayList<String> codesColliding = inverseMap.get(val);
    if(codesColliding == null) {
        codesColliding = new ArrayList<>(4);
        inverseMap.put(val, codesColliding);
    }
    codesColliding.add(code);
}  

这行得通,但我认为它不是最佳选择,因为我使用的内存比绝大多数键所需的内存更多。
尽管从编码角度来看它有效,但我想知道是否可以通过其他方式(通过其他数据结构)来实现这一点。
注意:我对纯Java 7(无额外的库)方法感兴趣

如果逆映射的值需要能够容纳原始映射中的多个键,则相对于不需要这样的情况,就无法避免一些开销。 您当前的方法还不错,但是如果原始地图值的很小一部分被重复,并且没有重复多次,那么对于您使用的列表的初始容量,我会更加怯st作为逆映射中的值。 为什么要预分配不止一个元素? 您几乎不需要重新分配,但是当您这样做时,列表将对您透明地进行处理。

也许最简单的方法是创建一个包含两个HashMap的类,一个用于非碰撞键,另一个用于碰撞键。 如果您以某种方式消除冲突的歧义(例如,您始终按字母顺序选择第一个),则可以将该逻辑添加到类中。 或者,如果您想返回ArrayLists,则可以将非冲突的字符串懒惰地包装到ArrayList中。

这全都在于了解您要对地图执行的操作。 如果您确信代码可以处理String和ArrayList结果之间的歧义,甚至可以牺牲一些类型安全性。

我知道您在谈论Map<String,String> ,但为清楚起见,让我们将其概括为Map<K,V> ,从中您将在其中构建Map<V,Collection<K>> 添加另一个Map<V,K> ,也许将其uniqueInverseMap 扫描条目时,请始终先在inverseMap检查密钥,然后再uniqueInverseMap 如果已经在uniqueInverseMap ,请将其删除,创建一个新的两元素列表,然后将该列表添加到inverseMap

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM