代码之家  ›  专栏  ›  技术社区  ›  Kaloyan Roussev

Java如何检测一段时间或操作后哈希图是否发生了变化?

  •  0
  • Kaloyan Roussev  · 技术社区  · 11 年前

    我想在某个时间点记录HashMap的状态。 然后用户可能会或可能不会更改它,当他们单击按钮时, 我想将HashMap的状态与之前保存的状态进行比较,看看是否有任何更改。

    我可以吗

    String firstState = map.toString();
    

    然后

    String secondState = map.toString();
    

    然后比较它们是否相等?

    编辑:我的意思是,如果HashMap发生任何变化,就会发生变化

    4 回复  |  直到 11 年前
        1
  •  5
  •   icza    11 年前

    要判断某个东西是否真的发生了变化,唯一的方法是复制地图,并在稍后的时间将其与地图进行比较:

    HashMap<String, String> m = new HashMap<>();
    // Populate map...
    
    // Save the state:
    HashMap<String, String> saved = new HashMap<>(m);
    
    // Clients might modify map here...
    
    // Test if the map was modified:
    boolean modified = saved.equals(m);
    

    HashMap.hashCode() 只能用来判断地图 已更改(如果哈希代码更改)。如果哈希代码没有更改,则不能保证映射没有更改。

    包装地图并覆盖 put() clear() 例如,方法也不够,因为如果某人使用 put() ,可能是他稍后会打电话 put() 再次设置您不再存储的旧值,并且无法判断是否恢复了相同的旧值。

    证明基于hascode的方法错误:

    如果地图包含 String 例如,我们可以将一个值更改为 一串 这样就可以轻松地使用相同的哈希代码 HashMap.hashCode() 不会改变。

    例如 一串 s都有相同的哈希码,但它们并不相等:

    String s1 = "";      // Hashcode = 0
    String s2 = "\0";    // Hashcode = 0
    String s3 = "\0\0";  // Hashcode = 0
    
    HashMap<String, String> m = new HashMap<>();
    m.put("one", s1);
    m.put("one", s2); // This does not change m.hashCode() yet its content changes!
    

    证明基于包装器的方法错误:

    HashMap<String, String> m = new HashMap<>();
    m.put("one", "1");
    
    // Now "save" state and modify the map via a wrapper
    
    Map<String, String> w = ...; // Create a wrapper
    
    w.put("one", "2"); // This will trigger that map is modified
    w.put("one", "1"); // This will trigger that map is modified, yet it is restored
    
    // Now the contents of the map is identical to the state that was saved.
    
        2
  •  2
  •   injecteer    11 年前

    您可以比较其“哈希值”

    int hash1 = map.hashCode();
    // do something
    int hash2 = map.hashCode();
    

    JavaDoc声明:

    映射的哈希代码定义为映射的entrySet()视图中每个条目的哈希代码之和

        3
  •  1
  •   Byungjoon Lee    11 年前

    或者,您可以将映射包装到一个包装器类中,该类记录最后修改的时间,无论是什么。使用该值,您可以检查是否有修改。

    如果您决定使用hashCode值来解决此问题,则应忽略可能存在哈希冲突的可能性。

    但在回答这个问题时,我认为有一个重要的方面需要考虑——钥匙的数量。如果没有太多的键,“copy construction+equals”方法将是基于包装器的解决方案的一个很好的替代方案。(先创建和复制旧的副本,然后将其与地图的当前状态进行比较)但是如果键太多,这两个操作可能会产生很大的开销。

        4
  •  0
  •   Delphin    11 年前

    你可以复制地图。

    HashMap old = new HashMap(map);
    

    然后检查旧映射是否包含与当前映射相同的键/值绑定,假设值正确实现了“equals”。

    if (!old.equals(map)) {
        System.out.println("Something changed");
    }