java中的地图问题

发布于 2024-11-28 10:39:47 字数 665 浏览 0 评论 0原文

我有一个包含 X 个元素的哈希图
我需要将此地图移至另一张地图
这就是我的代码的样子

Map originMap = initialize();
Map destMap = new Hashmap ();  

int originMapSize = originMap.size(); 
Set<Map.Entry<K, V>> entries = originMap.entrySet();
for (Map.Entry<K, Y> mapEntry : entries) {
 K key = mapEntry.getKey();
 V value = mapEntry.getValue();
 destMap.put (key,value);
}  

// Shouldnt this be equal to originMapSize ????
int destMapSize = destMap.size();

我观察到的是 - originMapSize 不等于 destMapSize

似乎当我们将元素放入 destMap 时,某些元素被覆盖

我们已经覆盖了 hashCode 和 equals 方法 - 它是可疑的实施。
但是,如果 originMap 允许添加元素,为什么 destinationMap 不添加新元素并覆盖现有元素?

I have a Hashmap which has X number of elements
I need to move this map into another map
This is what my code looks like

Map originMap = initialize();
Map destMap = new Hashmap ();  

int originMapSize = originMap.size(); 
Set<Map.Entry<K, V>> entries = originMap.entrySet();
for (Map.Entry<K, Y> mapEntry : entries) {
 K key = mapEntry.getKey();
 V value = mapEntry.getValue();
 destMap.put (key,value);
}  

// Shouldnt this be equal to originMapSize ????
int destMapSize = destMap.size();

What I am observing is - originMapSize is NOT equal to the destMapSize

It seems when we put the elements in the destMap, some of the elements are being overridden

We have overrridden the hashCode and equals method- and it is a suspicious implementation.
However, if the originMap allowed the elements to be added, why would the destinationMap not add a new elements and override an existing element instead ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

意中人 2024-12-05 10:39:47

如果 equals 方法不对称,则可能会发生这种情况。假设有两个键 a 和 b,使得:

  • a.hashCode() == b.hashCode()
  • a.equals(b) 返回 false
  • b。 equals(a) 返回 true

然后假设 HashMap 实现通过对具有相同值的每个现有键调用 existingKey.equals(newKey) 来搜索现有键哈希码作为新的 钥匙。

现在假设我们最初按照 { a, b } 的顺序添加它们。

第一个键 (a) 显然没有任何问题。第二个键 (b) 插入最终调用 a.equals(b) - 这是错误的,所以我们得到两个键。

现在构建第二个 HashMap,我们最终可能会以 { b, a } 的顺序获取条目。

这次我们首先添加 b,这很好......但是当我们插入第二个键 (a) 时,我们最终会调用 b.equals(a),它返回 true,因此我们覆盖该条目。

这可能不是正在发生的事情,但它可以解释一些事情 - 并显示不对称equals方法的危险。

编辑:这是一个简短但完整的程序,演示了这种情况。 (ab 的确切细节可能不同,但不对称性是相同的。)

import java.util.*;

public class Test {

    private final String name;

    public Test(String name)
    {
        this.name = name;
    }

    public static void main(String[] args)
    {
        Map<Test, String> firstMap = new HashMap<Test, String>();

        Test a = new Test("a");
        Test b = new Test("b");

        firstMap.put(b, "b");
        firstMap.put(a, "a");

        Map<Test, String> secondMap = new HashMap<Test, String>();
        for (Map.Entry<Test, String> entry : firstMap.entrySet())
        {
            System.out.println("Adding " + entry.getKey().name);
            secondMap.put(entry.getKey(), entry.getValue());
        }
        System.out.println(secondMap.size());
    }

    @Override public int hashCode()
    {
        return 0;
    }

    @Override public boolean equals(Object other)
    {
        return this.name.equals("b");
    }
}

我机器上的输出:

Adding a
Adding b
1

您可能无法以这种方式获得输出 - 它取决于:

  • equals 的调用方式(candidateKey.equals(newKey) 或反之亦然)
  • 从集合中返回条目的顺序

它甚至可能以不同的方式工作不同的运行。

This could happen if the equals method was asymmetric. Suppose there are two keys a and b such that:

  • a.hashCode() == b.hashCode()
  • a.equals(b) returns false
  • b.equals(a) returns true

Then suppose that the HashMap implementation searches for an existing key by calling existingKey.equals(newKey) for each existing key with the same hash code as the new key.

Now suppose we originally add them in the order { a, b }.

The first key (a) obviously goes in with no problems. The second key (b) insertion ends up calling a.equals(b) - which is false, so we get two keys.

Now building the second HashMap, we may end up getting the entries in the order { b, a }.

This time we add b first, which is fine... but when we insert the second key (a) we end up calling b.equals(a), which returns true, so we overwrite the entry.

That may not be what's going on, but it could explain things - and shows the dangers of an asymmetric equals method.

EDIT: Here's a short but complete program demonstrating this situation. (The exact details of a and b may not be the same, but the asymmetry is.)

import java.util.*;

public class Test {

    private final String name;

    public Test(String name)
    {
        this.name = name;
    }

    public static void main(String[] args)
    {
        Map<Test, String> firstMap = new HashMap<Test, String>();

        Test a = new Test("a");
        Test b = new Test("b");

        firstMap.put(b, "b");
        firstMap.put(a, "a");

        Map<Test, String> secondMap = new HashMap<Test, String>();
        for (Map.Entry<Test, String> entry : firstMap.entrySet())
        {
            System.out.println("Adding " + entry.getKey().name);
            secondMap.put(entry.getKey(), entry.getValue());
        }
        System.out.println(secondMap.size());
    }

    @Override public int hashCode()
    {
        return 0;
    }

    @Override public boolean equals(Object other)
    {
        return this.name.equals("b");
    }
}

Output on my machine:

Adding a
Adding b
1

You may not get the output that way round - it depends on:

  • The way that equals is called (candidateKey.equals(newKey) or vice versa)
  • The order in which entries are returned from the set

It may even work differently on different runs.

时光沙漏 2024-12-05 10:39:47

这些值应该相等,但问题是您正在迭代不同的 Map 对象。

for (Map.Entry mapEntry : entries)

不等于

for (Map.Entry mapEntry : originMap)

Those values should be equal, but the problem is you are iterating over a different Map object.

for (Map.Entry mapEntry : entries)

is not the same as

for (Map.Entry mapEntry : originMap)
苍暮颜 2024-12-05 10:39:47

我怀疑添加到第一个哈希映射的元素顺序与添加到第二个哈希映射的元素顺序不同。这与粗略的 hashCode 方法相结合,导致重复项添加到第一个方法中。

尝试更改 hashCode 以始终返回相同的值,看看问题是否消失。

I suspect the order of the elements being added to the first hashmap is not the same as the order added to the second. This combined with the sketchy hashCode method is causing duplicates to be added to the first.

Try changing hashCode to always return the same value to see if your problem goes away.

爱已欠费 2024-12-05 10:39:47

为什么不使用 destMap.putAll(originMap) ?

Why don't you use destMap.putAll(originMap) ?

不忘初心 2024-12-05 10:39:47

Map 有一个 putAll 方法。尝试这样的事情:

    Map<String, String> destination = new HashMap<String, String>();
    Map<String, String> original = new HashMap<String, String>();

    destination.putAll(original);

Map has a putAll method. Try something like this:

    Map<String, String> destination = new HashMap<String, String>();
    Map<String, String> original = new HashMap<String, String>();

    destination.putAll(original);
巾帼英雄 2024-12-05 10:39:47

这取决于第一个 HashMap 是如何初始化的。此外,每次将对象添加到 HashMap 中时,一旦它通过 75% 的负载因子,它就会分配默认大小的两倍来容纳新值。地图的默认大小通常为 16:当您超过 75% 的负载系数时,它会放大到 32。

It depends of how the first HashMap is initialized. Also everytime you add an object into the HashMap , once it passes 75% load factor, it allocates twice the default size to accomodate new values. Maps usually have default size = 16: when you pass the 75% load factor it enlarges to 32.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文