使用包含空字段的复合键读取 Multimap
Reading Multimap with composite key including null field
我有一个 Multimap
来存储一些具有复合键(数据类型、数据 ID)的数据。
这是我的代码:
public class Data {
private final String type;
private final Integer id;
private final String information;
public Data(String type, Integer id, String information) {
this.type = type;
this.id = id;
this.information = information;
}
@Override
public String toString() {
return "Type: " + type + ", ID: " + id + ", Info: " + information;
}
}
public class Test {
private static Multimap<Key, Data> data = HashMultimap.create();
static class Key {
private final String type;
private final Integer id;
public Key(String type, Integer id) {
this.type = type;
this.id = id;
}
@Override
public int hashCode() {
//System.out.println("in hashcode");
return Objects.hashCode(type);
}
@Override
public boolean equals(Object obj) {
//System.out.println("in equals");
if (obj == null) {
return false;
}
if (!(obj instanceof Key)) {
return false;
}
Key other = (Key) obj;
if (other.type.equals(type)) {
if (other.id == null) { // Return true for null ID Data
return true;
} else if (other.id.equals(id)) {
return true;
}
}
return false;
}
}
private static void addData(String type, Integer id, String information) {
data.put(new Key(type, id), new Data(type, id, information));
}
private static void printData(String type, Integer id) {
System.out.println("\n===============");
System.out.println("Filtered Data for: Type => " + type + ", ID => " + id);
for (Data d : data.get(new Key(type, id))) {
System.out.println(d);
}
}
public static void main(String[] args) {
addData("confidential", 11, "Some Confidential Data!");
addData("private", 21, "Some Private Data!");
addData("government", 13, "Some Govt. Data!");
addData("public", null, "Some public data!");
addData("public", 26, "Another public data!");
addData("public", 4, "More public information!");
addData("unspecified", null, "Lorem ipsum dolor sit amet!");
addData("unspecified", 15, "consectetur adipiscing elit.");
addData("unspecified", 25, "Integer sed velit vel.");
addData("unspecified", null, "In vitae velit consequat");
printData("unspecified", 25);
printData("public", 26);
}
}
现在,我想按 Data::type
和 Data::id
过滤此数据,包括 Data::type
匹配但 Data::id
为 null
的数据。
预期输出:
===============
Filtered Data for: Type => unspecified, ID => 25
Type: unspecified, ID: null, Info: In vitae velit consequat
Type: unspecified, ID: null, Info: Lorem ipsum dolor sit amet!
Type: unspecified, ID: 25, Info: Integer sed velit vel.
===============
Filtered Data for: Type => public, ID => 26
Type: public, ID: null, Info: Some public data!
Type: public, ID: 26, Info: Another public data!
实际输出
===============
Filtered Data for: Type => unspecified, ID => 25
Type: unspecified, ID: null, Info: In vitae velit consequat
Type: unspecified, ID: 15, Info: consectetur adipiscing elit.
Type: unspecified, ID: null, Info: Lorem ipsum dolor sit amet!
Type: unspecified, ID: 25, Info: Integer sed velit vel.
===============
Filtered Data for: Type => public, ID => 26
Type: public, ID: 4, Info: More public information!
Type: public, ID: null, Info: Some public data!
Type: public, ID: 26, Info: Another public data!
为此,我在 Key
class 中实现了 hashCode()
和 equals()
方法,并在其他数据对象 [=23] 时返回 true
=] 是 null
.
问题:
我使用的方法是否正确,或者这可以使用简单的方法实现 Map
?
为什么在我调用Multimap::get()
方法时,hashCode
和equals
方法只被调用一次? (根据我的说法,地图中的每个键都应该与指定的键匹配!)
如果是正确的方法,如何实现equals
方法以获得预期的结果?
为了使哈希映射正常工作,equals 实现必须满足以下约束:如果 a.equals(b)
和 b.equals(c)
则 a.equals(c)
必须为真。如果您打破该约束,则地图的行为将不可预测。这个 属性 叫做传递性。查看 equals 实现的完整约束列表 here。
要执行您想要的操作,您必须在 printData
方法中执行两次查找,一次使用 new Key(type, id)
,一次使用 new Key(type, null)
。巧妙的 equals 实现没有捷径。
要回答这个问题,为什么您在调用 get()
时看到 hashCode
和 equals
只调用了一次?这是对 equals
的约束的另一个结果。根据您的equals
实现,地图已经确定Key(x, 15)
和Key(x, null)
是相同的。这是在您插入数据时完成的。因此在查找时,它只需与其中一个进行比较,然后假定另一个也匹配。
我有一个 Multimap
来存储一些具有复合键(数据类型、数据 ID)的数据。
这是我的代码:
public class Data {
private final String type;
private final Integer id;
private final String information;
public Data(String type, Integer id, String information) {
this.type = type;
this.id = id;
this.information = information;
}
@Override
public String toString() {
return "Type: " + type + ", ID: " + id + ", Info: " + information;
}
}
public class Test {
private static Multimap<Key, Data> data = HashMultimap.create();
static class Key {
private final String type;
private final Integer id;
public Key(String type, Integer id) {
this.type = type;
this.id = id;
}
@Override
public int hashCode() {
//System.out.println("in hashcode");
return Objects.hashCode(type);
}
@Override
public boolean equals(Object obj) {
//System.out.println("in equals");
if (obj == null) {
return false;
}
if (!(obj instanceof Key)) {
return false;
}
Key other = (Key) obj;
if (other.type.equals(type)) {
if (other.id == null) { // Return true for null ID Data
return true;
} else if (other.id.equals(id)) {
return true;
}
}
return false;
}
}
private static void addData(String type, Integer id, String information) {
data.put(new Key(type, id), new Data(type, id, information));
}
private static void printData(String type, Integer id) {
System.out.println("\n===============");
System.out.println("Filtered Data for: Type => " + type + ", ID => " + id);
for (Data d : data.get(new Key(type, id))) {
System.out.println(d);
}
}
public static void main(String[] args) {
addData("confidential", 11, "Some Confidential Data!");
addData("private", 21, "Some Private Data!");
addData("government", 13, "Some Govt. Data!");
addData("public", null, "Some public data!");
addData("public", 26, "Another public data!");
addData("public", 4, "More public information!");
addData("unspecified", null, "Lorem ipsum dolor sit amet!");
addData("unspecified", 15, "consectetur adipiscing elit.");
addData("unspecified", 25, "Integer sed velit vel.");
addData("unspecified", null, "In vitae velit consequat");
printData("unspecified", 25);
printData("public", 26);
}
}
现在,我想按 Data::type
和 Data::id
过滤此数据,包括 Data::type
匹配但 Data::id
为 null
的数据。
预期输出:
===============
Filtered Data for: Type => unspecified, ID => 25
Type: unspecified, ID: null, Info: In vitae velit consequat
Type: unspecified, ID: null, Info: Lorem ipsum dolor sit amet!
Type: unspecified, ID: 25, Info: Integer sed velit vel.
===============
Filtered Data for: Type => public, ID => 26
Type: public, ID: null, Info: Some public data!
Type: public, ID: 26, Info: Another public data!
实际输出
===============
Filtered Data for: Type => unspecified, ID => 25
Type: unspecified, ID: null, Info: In vitae velit consequat
Type: unspecified, ID: 15, Info: consectetur adipiscing elit.
Type: unspecified, ID: null, Info: Lorem ipsum dolor sit amet!
Type: unspecified, ID: 25, Info: Integer sed velit vel.
===============
Filtered Data for: Type => public, ID => 26
Type: public, ID: 4, Info: More public information!
Type: public, ID: null, Info: Some public data!
Type: public, ID: 26, Info: Another public data!
为此,我在 Key
class 中实现了 hashCode()
和 equals()
方法,并在其他数据对象 [=23] 时返回 true
=] 是 null
.
问题:
我使用的方法是否正确,或者这可以使用简单的方法实现
Map
?为什么在我调用
Multimap::get()
方法时,hashCode
和equals
方法只被调用一次? (根据我的说法,地图中的每个键都应该与指定的键匹配!)如果是正确的方法,如何实现
equals
方法以获得预期的结果?
为了使哈希映射正常工作,equals 实现必须满足以下约束:如果 a.equals(b)
和 b.equals(c)
则 a.equals(c)
必须为真。如果您打破该约束,则地图的行为将不可预测。这个 属性 叫做传递性。查看 equals 实现的完整约束列表 here。
要执行您想要的操作,您必须在 printData
方法中执行两次查找,一次使用 new Key(type, id)
,一次使用 new Key(type, null)
。巧妙的 equals 实现没有捷径。
要回答这个问题,为什么您在调用 get()
时看到 hashCode
和 equals
只调用了一次?这是对 equals
的约束的另一个结果。根据您的equals
实现,地图已经确定Key(x, 15)
和Key(x, null)
是相同的。这是在您插入数据时完成的。因此在查找时,它只需与其中一个进行比较,然后假定另一个也匹配。