【问题标题】:Comparing hastable with equals比较 hastable 和 equals
【发布时间】:2023-03-15 07:03:01
【问题描述】:

我有一个相当愚蠢的问题,但我想知道在编译器为我们做之前将哈希映射的输入与equals() 进行比较是否可以实现。我正在尝试计算我在地图中输入重复键值对的次数。

我已经编写了一些代码,但我不知道如何实现equals()。有什么想法吗?

Map<String, String> newMap = new LinkedHashMap<>();
    newMap.put("aaa", "bbb");
    newMap.put("ccc", "ddd");
    newMap.put("eee", "fff");
    newMap.put("aaa", "bbb");
    System.out.println(newMap.size());

    for(String item : newMap.keySet()){
        System.out.println(item + " "+newMap.get(item));

    }

【问题讨论】:

  • 你到底想做什么?你的问题有点不清楚。
  • 您希望结构为您执行此操作吗? (它没有 - 您需要自己编写。)根据定义,Map 每个键只会存储一个值,因此如果您使用键 "aaa" 添加一些值,然后添加第二个具有相同值的值键,第一个是替换。您可以(在您自己的代码中)使用newMap.containsKey() 来查看密钥是否已存在于Map 中。
  • 如果您打算为同一个键存储多个值,则使用Map&lt;String, List&lt;String&gt;&gt; 的结构是很常见的。
  • 你不能在这些内置类型上实现 equals 自己。至少提供一个使用 equals 的例子,即使没有实现。
  • equals 与跟踪put 调用次数有什么关系?

标签: java hashmap equals


【解决方案1】:

你不能用一张地图来做这件事,但你可以用它的抽象来做一些事情。

这是一个与 Java 8 兼容的示例;使用两个映射,我们能够保持完整的标签何时将特定键输入映射并基于键递增。假设这是在一个单独的类中定义的。

Map<K, V> newMap = new LinkedHashMap<>();
Map<K, Integer> newMapOccurrences = new HashMap<>();

public void put(K key, V value) {
    newMap.put(key, value);
    newMapOccurrences.put(key, newMapOccurrences.getOrDefault(key, 0) + 1);
}

public Integer getCount(K key) {
    return newMapOccurrences.getOrDefault(key, 0);
}

如果您想确保跟踪键值对,那就有点棘手了,因为不建议使用映射作为键条目。此外,由于 map 无论如何都与键无关,因此尝试同时跟踪两者并不是最好的主意,而且您可能会得到一个错误的计数。但是,我确实以Map&lt;String, Map&lt;String, Integer&gt;&gt;&gt; 的形式提供了一个想法,可能让您在该努力中朝着正确的方向开始;但是,我把它留给读者作为练习。

【讨论】:

    【解决方案2】:

    做到这一点的一种方法是保留一个 Map 来跟踪您为 K 类型的给定键调用 map.put() 的次数。

    如果您希望 put 操作自动为您跟踪,您可以拥有一个扩展 LinkedHashMap 的新 Map 类。然后,put 操作将跟踪插入计数,例如

    public class KeyCountMap<K,V> extends LinkedHashMap<K,V> {
      private HashMap<K, Integer> keyCountMap;
    
      public KeyCountMap() {
        this.keyCountMap = new HashMap<K, Integer>();
      }
    
      @Override
      public V put(K key, V value) {
        keyCountMap.put(key, keyCountMap.getOrDefault(key, 0) + 1);
        return super.put(key, value);
      }
    
      public int fetchKeyCount(K key) {
        return keyCountMap.getOrDefault(key, 0);
      }
    }
    

    使用此映射,您可以通过调用 fetchKeyCount 来获取您的密钥插入计数,例如

      KeyCountMap<String, String> newMap = new KeyCountMap<>();
      newMap.put("aaa", "bbb");
      newMap.put("ccc", "ddd");
      newMap.put("eee", "fff");
      newMap.put("aaa", "bbb");
      System.out.println(newMap.fetchKeyCount("aaa"));
    

    编辑:修改每个 cmets 的代码以删除本地 LinkedHashMap 字段并添加 Java 8 getOrDefault 方法。

    【讨论】:

    • 正确的想法,但 Java 8 使用 getOrDefault 使这变得不那么冗长。
    • 我们的解决方案类似;我玩弄了检查是否包含该值的想法,但如果未包含该值,则无论如何它都会获得基值 1。因此,Java 8 大大简化了它。
    • 是的,我认为使用 getOrDefault 更好,它还为不存在的键提供 0 而不是 NPE,这更有意义。
    【解决方案3】:
    public final class PutCountingLinkedHashMap<K, V> extends LinkedHashMap<K, V> {
        private final Map<K, Integer> putCounts = new HashMap<>();
    
        @Override
        public V put(final K key, final V value) {
            final int count = count(key);
            putCounts.put(key, count + 1);
            return super.put(key, value);
        }
    
        public int count(final K key) {
            return putCounts.getOrDefault(key, 0);
        }
    
        public int totalDuplicatePuts() {
          int total = 0;
            for (int i : putCounts.values()) {
                if (i > 1) total += i - 1;
            }
            return total;
        }
    }
    

    用法:

    PutCountingLinkedHashMap<String,String> map = new PutCountingLinkedHashMap<>();
    map.put("aaa", "bbb");
    map.put("ccc", "ddd");
    map.put("eee", "fff");
    map.put("aaa", "bbb");
    
    int aaaCount = map.count("aaa"); //2
    

    需要额外的工作来决定如何处理 removeclear 等的计数。

    我正在尝试计算我在地图中输入重复键值对的次数

    map.totalDuplicatePuts();
    

    【讨论】:

    • 你的速度更快,现在我有一个非常相似的答案:-)
    • @vsnyc 但是为什么你的有一个private LinkedHashMap&lt;K,V&gt; map; 字段?它要么支持接口Map 并提供支持字段,要么继承自LinkedHashMap,但不能同时继承。
    • 我会修复它,我首先构建一个包装器,然后扩展 LinkedHashMap&lt;K,V&gt; 并将两者混合。
    【解决方案4】:

    我建议编写您的自定义“HashMap”类,它应该实现 Comparable 接口,然后在调用 super.put(k) 之前覆盖应该使用自定义 compareTo(o) 实现的 put(k,v) 方法,v)。这是一个例子:

        public class MyMap<K,V> extends HashMap<K,V> implements Comparable<Object>{
    
            @Override
            public V put(K key, V value){
    
                //Use your custom compareTo method to see if the key already exist, before the HasMap class does it.
                if(compareTo(key) != 0){
                    super.put(key, value);
                    return value;
                }else{
                    //Do something else
                }
                return null;
            }
    
            @Override
            public int compareTo(Object o) {
                //Implement your desire logic to compare
                //Test if the o object is an instance of desired class
                for(K item : this.keySet()){
                    if(o.equals(item))
                        return 0;
                }
                return -1;
            }
        }
    

    【讨论】:

    • 不是Comparable&lt;Object&gt; 的粉丝。为什么它需要具有可比性?
    猜你喜欢
    • 1970-01-01
    • 2020-05-28
    • 2014-08-07
    • 2013-02-16
    • 2010-12-17
    • 2016-02-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-18
    相关资源
    最近更新 更多