在我的几个地方的项目中,我使用HashMap。我的每个HashMap都应该有一个包含以下几个字段的键:
public Long campaignId;
public Integer regionId;
public String posaLang;
public String audienceCode;
public String theme;
public GroupKey(Long campaignId,
Integer regionId,
String posaLang,
String audienceCode,
String theme) {
this.campaignId = campaignId;
this.regionId = regionId;
this.posaLang = posaLang;
this.audienceCode = audienceCode;
this.theme = theme;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AdGroupKey that = (AdGroupKey) o;
return new EqualsBuilder()
.append(regionId, that.regionId)
.append(posaLang, that.posaLang)
.append(audienceCode, that.audienceCode)
.append(theme, that.theme)
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(regionId)
.append(posaLang)
.append(audienceCode)
.append(theme)
.toHashCode();
}
}
这是如此庞大的代码量,对于每个HashMap,我应该像上面那样编写一个密钥类。有没有办法避免这些物体的巨大影响?
答案 0 :(得分:1)
如果标题为“HashMap中复合键的最佳方法”,我怀疑你的问题会吸引更多观点。
有许多选择可供选择,并且为每种键类型使用单独的类可能是最佳选择。它是规范和安全的,因为它可以表示由每个字段的可能值的任意组合构成的任何可能的值。为了最大限度地减少空间开销,请考虑一下您是否真的需要campaignId
成为Long
对象,或者仅仅是原始long
- 换句话说,它是否可以为空?
您可以将所有字段组合成一个字符串,这可以节省空间,然后将所有字段连续存储在内存中,而不是使用单独的引用变量。但这可能很棘手。你会用什么作为字段之间的分隔符?你确定这个分隔符永远不会成为字段的一部分吗?
您可以单独存储每个字段,如原始选项中所示,但无需为每个键类型编写类。您所需要的只是一个集合类,它可以存储所有字段并提供使用字段值的合适hashCode
和equals
方法。实际上,List接口提供了这个功能。它的hashCode和equals方法规范正是您所需要的。它们依次组合每个字段的hashCode和equals方法。
因此,只需使用List:
而不是类List<Object> myKey = Arrays.asList(campaignId, regionId, posaLang, audienceId);
HashMap<List<?>, ValueClass> myMap = new HashMap<>();
myMap.put(myKey, myValue);
myValue = myMap.get(Arrays.asList(campaignId, regionId, posaLang, audienceId));
优点:方便,您不必为每个密钥编写一个类。
缺点:缺乏类型安全性。您不能拥有同类列表,因此所有字段都必须是Object类型。无法防止创建包含太多或太少对象的列表或错误类型的对象。