Java 在HashMap中查找包含字符的所有键并替换它

Java 在HashMap中查找包含字符的所有键并替换它,java,key,hashmap,Java,Key,Hashmap,我有一个HashMap,现在我需要找到HashMap中的所有键,其中包含一个特定的字母,并用另一个字母替换它,因此您想要更改键。如果Hashalgorithm不是什么奇怪的东西,那么您必须获取所有键值对,从hashmap中删除它们,更改它们并重新插入它们。或者将它们插入新的Hashmap。您可以尝试以下方法: public void replaceKeysChar(char originalChar, char newChar, Map<String, ?> map) { M

我有一个HashMap,现在我需要找到HashMap中的所有键,其中包含一个特定的字母,并用另一个字母

替换它,因此您想要更改键。如果Hashalgorithm不是什么奇怪的东西,那么您必须获取所有键值对,从hashmap中删除它们,更改它们并重新插入它们。或者将它们插入新的Hashmap。

您可以尝试以下方法:

public void replaceKeysChar(char originalChar, char newChar, Map<String, ?> map) {
    Map<String, Object> tempMap = new HashMap<String, Object>();
    for (Map.Entry<String, ?> entry : map.entrySet()) {
        String key = entry.getKey();
        if(key != null){
            key = key.replace(originalChar, newChar);
        }
        tempMap.put(key, entry.getValue());
    }
    map.clear();
    map.putAll(tempMap);
}
  • 构造一个新的hashmap
  • 复制所有 (键,值)来自旧 hashmap,除了替换 键中的OLDCHAR和NEWCHAR
  • 交换 散列映射结束

  • 我想人们会担心你不能在原地更改字符串键,因为字符串的哈希代码与字符串的值绑定在一起。添加/删除键可能会起作用,但随后可能会发生冲突,最终会意外地替换现有字符串

    解决此问题最明显的方法是使用自定义密钥,例如

    public class MyKey {
      static private Random r = new Random();
    
      private String keyValue; 
      private final int hashCode = r.nextInt();
    
      @Override
      public int hashCode() {
        return hashCode;
      }
    
      public void setKeyValue(String keyValue) {
        this.keyValue = keyValue;
      }
    
      public String getKeyValue() {
        return keyValue;
      }
    }
    
    这个键有一个字符串键值,您可以很容易地设置/获取它,还有一个哈希代码,它只是一个随机数。将此键添加到哈希映射后,可以在不添加或删除键的情况下原位更改字符串。您所需要做的就是迭代密钥集,并对密钥执行任何您喜欢的处理,所有这些都不会影响哈希代码或运行冲突风险或其他任何事情

    这里有一个通过抛出异常来“处理”冲突的解决方案

    public void replaceKeysChar(char originalChar, char newChar, Map<String, ?> map) {
        Map<String, Object> tempMap = new HashMap<String, Object>();
        Set<String> tempSet = new HashSet<String>();
        for (Map.Entry<String, ?> entry : map.entrySet()) {
            String originalKey = entry.getKey();
            String newKey = originalKey .replace(originalChar, newChar);
            if (!newKey.equals(originalKey)) {
                if (map.containsKey(newKey) || tempMap.containsKey(newKey)) {
                    throw new CollisionException(newKey);
                }
                tempMap.put(newKey, entry.getValue());
                tempSet.add(originalKey());
            }
        }
        map.keySet().removeAll(tempSet);
        map.putAll(tempMap);
    }
    
    public void replaceKeyChar(char originalChar、char newChar、Map){
    Map tempMap=newhashmap();
    Set tempSet=newhashset();
    对于(Map.Entry:Map.entrySet()){
    String originalKey=entry.getKey();
    字符串newKey=originalKey.replace(originalChar,newChar);
    如果(!newKey.equals(originalKey)){
    if(map.containsKey(newKey)| tempMap.containsKey(newKey)){
    抛出新的冲突异常(newKey);
    }
    put(newKey,entry.getValue());
    add(originalKey());
    }
    }
    map.keySet().removeAll(tempSet);
    map.putAll(tempMap);
    }
    
    编辑


    修正错误。。。在以前的版本中。

    你能用上面的方法展示一个小例子吗,它会帮助我lot@JohnreplaceKeyChar('k','j','yourMap);我不明白我怎么能更明确地感谢你让我知道。现在我可以思考,这就是你的答案,所以删除了+1,我忽略了碰撞部分(假设OP知道它会做什么),但是你指定它是正确的。我不确定这个策略是否方便。您需要始终保留对每个特定MyKey实例的引用,因为无法恢复哈希代码。但是如果你必须跟踪MyKey,为什么不首先跟踪它的值呢?Barthelemy,在我看来,一个键是对hashmap中数据的唯一引用。如果更改密钥(例如,将一个字符串更改为另一个字符串),则可能会发生冲突和其他不愉快的情况。因此,密钥应该是唯一的,但可以访问有效负载。hashcode只是hashmap的一个提示。严格地说,它应该尽可能唯一,但它只是由算法在选择将密钥放入哪个存储桶时使用。它通常与equals()结合使用。碰撞的可能性是该问题不可避免的一部分,OP需要指定发生碰撞时他希望发生的情况。代码是否应该抛出异常?它是否应该悄悄地丢失其中一个条目?还有什么?你为什么要这么做?这不是HashMap特别擅长的操作;可能有一种完全不同的解决方案可以使用。@John
    replaceKeyChar('k','j',yourMap)
    @Stephen C,此方法不会删除旧密钥(在替换之前),而
    map.clear()
    (删除旧密钥)也会删除未更改的密钥。@Colin-我在您之前就发现了它:-P。现在修复了。@Stephen C,我发现这个方法有点“沉重”,需要额外的
    集。另外,它不会处理
    null
    值(也不会处理
    null
    键[我刚刚修复过])@Colin-它更复杂,但假设您只重命名一小部分条目,它应该会更高效。修复了空值的情况。空键的情况是不可能的。这种解决方案比那些就地更新hashmap的解决方案更可取。它可能更快;更容易验证是否正确;并且更灵活地使用(在需要保留旧hashmap的情况下)。
    public void replaceKeysChar(char originalChar, char newChar, Map<String, ?> map) {
        Map<String, Object> tempMap = new HashMap<String, Object>();
        Set<String> tempSet = new HashSet<String>();
        for (Map.Entry<String, ?> entry : map.entrySet()) {
            String originalKey = entry.getKey();
            String newKey = originalKey .replace(originalChar, newChar);
            if (!newKey.equals(originalKey)) {
                if (map.containsKey(newKey) || tempMap.containsKey(newKey)) {
                    throw new CollisionException(newKey);
                }
                tempMap.put(newKey, entry.getValue());
                tempSet.add(originalKey());
            }
        }
        map.keySet().removeAll(tempSet);
        map.putAll(tempMap);
    }