英文:
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("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()));
//output
A:test1
B:test2
//test 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()));
//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<Box, String> treeMap = new TreeMap<>((a,b)-> 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论