[英]HashMap getting key given that I already have the key
这听起来像是一个非常奇怪的请求,但我有一个自定义类的HashMap
。 我已经覆盖了equals
和hashCode
方法以只关注某些字段,这样我就可以在它等于具有相同某些字段的新键时拉出一个键。 在这种情况下,我想用一些新值替换其他字段。 结构是这样的:
public class ExampleClass() {
int field1;
int field2;
<insert constructor here with field1 and field2>
@Override
public boolean equals(Object obj) { // Only return true if field1 is equal
...
return (this.field1 == obj.field1);
}
}
所以我像这样使用它:
HashMap<ExampleClass, int> hmap = new HashMap<>();
while(true) {
...
ExampleClass oldObject = new ExampleClass(1, 2);
ExampleClass newObject = new ExampleClass(1, 5);
hmap.put(oldObject, 10);
if(hmap.contains(newObject)) {
// Get field1 of old object and change it
}
}
这是一个不好的例子,但我只想能够在HashMap
检索键值对的键对象,因为我有键,以便我可以修改键。 我该怎么做?
编辑:我的哈希码函数。
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result +
((this.srcVertex.getVertexData().getID() == null) ? 0 : this.srcVertex.getVertexData().getID().hashCode());
result = prime * result +
((this.targetVertex.getVertexData().getID() == null) ? 0 : this.targetVertex.getVertexData().getID().hashCode());
return result;
}
据我了解您的问题,您在 HashMap 中有一个键对象,并且您想使用“相等”键对象来检索键而不是与其关联的值。 HashMap 上没有方法可以做到这一点,如果您确实关心获得的两个相等对象中的哪一个,那么它在某种程度上违反了两个对象“相等”的想法。
我认为以不同的方式执行此操作会更有意义:
ExampleKey
其中仅包含您想在equals
/ hashCode
方法中用于 HashMap 的字段。 此类必须使用这些字段覆盖equals
和hashCode
,并且它应该是不可变的(如果键的哈希值在 HashMap 中可以更改,则行为未定义)。ExampleClass
一个getKey()
方法,该方法返回当前对象的ExampleKey
对象。 在这里使用组合可能更简单,因此ExampleClass
不会重复这些字段。Map<ExampleKey, Integer>
用于您要存储的实际映射,以及一个单独的Map<ExampleKey, ExampleClass>
存储对象,否则该对象将被用作另一个 HashMap 中的键。用法示例:
Map<ExampleKey, Integer> actualMapping = new HashMap<>();
Map<ExampleKey, ExampleClass> objsUsed = new HashMap<>();
while(true) {
// ...
ExampleClass oldObject = new ExampleClass(1, 2);
ExampleClass newObject = new ExampleClass(1, 5);
// always update both maps together, to ensure valid state
actualMapping.put(oldObject.getKey(), 10);
objsUsed.put(oldObject.getKey(), oldObject);
// ...
ExampleClass objUsed = objsUsed.get(newObject.getKey());
if(objUsed != null) {
// objUsed == oldObject here
}
}
如果您不关心“相等”的含义,那么您可以在没有ExampleKey
类或getKey
方法的情况下应用相同的解决方案; 只使用对象本身,即objsUsed
将是Map<ExampleClass, ExampleClass>
,它总是将对象映射到自身。 但我认为如果你这样做,你的代码的读者会挠头想知道你为什么要将对象映射到它们自己。
您忘记定义 hashCode() 方法。 没有它,将对象作为键存储在 HashMap 中是行不通的。
更新:
如果 srcVertex 是 field1 而 targetVertex 是 field2,那么你的 hashCode() 方法是不正确的。 如果equals() 比较srcVertex,那么hashCode() 应该只使用srcVertex,而不是targetVertex。
规则是:如果 2 个对象相等,则它们的哈希码必须相等。
Java 中的Map
应该以在其所有“基本属性”上定义了equals
值作为键。 我相信大多数收藏库都是这样工作的,唯一能想到的例子是 General Magic 的 Telescript。
因此,在仅具有这些属性的类型上定义Map
。 在这种情况下, field1
int
( Integer
)。 将其余信息放入映射条目值中。 这很可能是一个新类。
Map<Integer, ValueClass> map;
在哪里
public final class ValueClass {
private int someValue;
private ExampleClass exmaple;
...
如果你坚持要找到钥匙,我建议你不要。 有多种方法可以做到,例如:
Optional<ExampleClass> found = map.keySet().stream()
.firstThat(k -> k.field1() == target);
found.ifPresent(key -> {
Integer value = hmap.remove(key);
// update key.
hmap.put(key, value);
});
或者旧学校版本(对我来说看起来更好,但不是那么酷):
for (ExampleClass key : map.keySet()) {
if (key.field1() == target) {
Integer value = hmap.remove(key);
// update key.
hmap.put(key, value);
}
}
使用Iterator
或可能在 ihe 条目集上使用更好,因为它避免了三个查找中的第二个,但我将把它作为练习。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.