Java TreeMap put vs HashMap put, custom Object as key

huangapple go评论75阅读模式
英文:

Java TreeMap put vs HashMap put, custom Object as key

问题

我的目标是使用 TreeMap,通过 Box.volume 属性对 Box key 对象进行排序,同时能够通过 Box.code 区分不同的键。在 TreeMap 中是否不可能实现这一点?

根据下面的测试 1,HashMap 的 put 操作按预期工作,HashMap 保留了 A、B 两个键对象,但在测试 2 中,TreeMap 的 put 操作似乎没有将 D 视为不同的键,它替换了 C 的值,需要注意的是,我在 TreeMap 中使用了 Box.volume 作为比较器,因为我希键按照体积在 TreeMap 中排序。

import java.util.*;

public class MapExample {
    public static void main(String[] args) {
        // 测试 1
        Box b1 = new Box("A");
        Box b2 = new Box("B");
        Map<Box, String> hashMap = new HashMap<>();
        hashMap.put(b1, "test1");
        hashMap.put(b2, "test2");
        hashMap.entrySet().stream().forEach(o -> System.out.println(o.getKey().code + ":" + o.getValue()));
        // 输出
        A:test1
        B:test2

        // 测试 2
        Box b3 = new Box("C");
        Box b4 = new Box("D");
        Map<Box, String> treeMap = new TreeMap<>((a, b) -> Integer.compare(a.volume, b.volume));
        treeMap.put(b3, "test3");
        treeMap.put(b4, "test4");
        treeMap.entrySet().stream().forEach(o -> System.out.println(o.getKey().code + ":" + o.getValue()));
        // 输出
        C:test4
    }
}

class Box {
    String code;
    int volume;

    public Box(String code) {
        this.code = code;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Box box = (Box) o;
        return code.equals(box.code);
    }

    @Override
    public int hashCode() {
        return Objects.hash(code);
    }
}

谢谢。

英文:

My objective was to use the TreeMap to make Box key objects sorted by Box.volume attribute while able to put keys distinct by the Box.code. Is it not possible in TreeMap?

As per below test 1, HashMap put works as expected, HashMap keeps both A, B key objects, but in test 2, TreeMap put doesn't treat D as a distinct key, it replaces C's value, note that i used the TreeMap comparator as Box.volume, because i want keys to be sorted by volume in TreeMap.

import java.util.*;
public class MapExample {
public static void main(String[] args) {
//test 1
Box b1 = new Box(&quot;A&quot;);
Box b2 = new Box(&quot;B&quot;);
Map&lt;Box, String&gt; hashMap = new HashMap&lt;&gt;();
hashMap.put(b1, &quot;test1&quot;);
hashMap.put(b2, &quot;test2&quot;);
hashMap.entrySet().stream().forEach(o-&gt; System.out.println(o.getKey().code+&quot;:&quot;+o.getValue()));
//output
A:test1
B:test2
//test 2
Box b3 = new Box(&quot;C&quot;);
Box b4 = new Box(&quot;D&quot;);
Map&lt;Box, String&gt; treeMap = new TreeMap&lt;&gt;((a,b)-&gt; Integer.compare(a.volume, b.volume));
treeMap.put(b3, &quot;test3&quot;);
treeMap.put(b4, &quot;test4&quot;);
treeMap.entrySet().stream().forEach(o-&gt; System.out.println(o.getKey().code+&quot;:&quot;+o.getValue()));
//output
C:test4
}
}
class Box {
String code;
int volume;
public Box(String code) {
this.code = code;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Box box = (Box) o;
return code.equals(box.code);
}
@Override
public int hashCode() {
return Objects.hash(code);
}
}

Thank you

答案1

得分: 5

TreeMap认为如果比较方法返回0,则考虑两个键是相同的,即使它们彼此不相等,所以您当前的TreeMap不能包含具有相同体积的两个键。

如果您想保持按卷排序,并且仍然希望在您的Map中具有具有相同体积的多个键,请将您的Comparator的比较方法更改为在体积相等时比较Box的代码。这样只有在键相等时才会返回0。

Map<Box, String> treeMap = new TreeMap<>((a, b) -> a.volume != b.volume ? Integer.compare(a.volume, b.volume) : a.code.compareTo(b.code));

现在的输出是:

C:test3
D:test4
英文:

TreeMap considers 2 keys for which the comparison method returns 0 to be identical, even if they are not equal to each other, so your current TreeMap cannot contain two keys with the same volume.

If you want to keep the ordering by volume and still have multiple keys with the same volume in your Map, change your Comparator's comparison method to compare the Box's codes when the volumes are equal. This way it will only return 0 if the keys are equal.

Map&lt;Box, String&gt; treeMap = new TreeMap&lt;&gt;((a,b)-&gt; a.volume != b.volume ? Integer.compare(a.volume, b.volume) : a.code.compareTo(b.code));

Now the output is:

C:test3
D:test4

答案2

得分: 0

b3 和 b4 有相同的体积,即 0(int 默认值)。

为使其工作,请在比较之前为 Box 的体积变量赋值。

英文:

b3 and b4 has the same volume, that is 0 (int default value).

For it work, assign a value to the Box volume variables before comparing.

huangapple
  • 本文由 发表于 2020年9月23日 10:57:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/64020405.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定