我在接受采访时被问到这个问题。使用Google Guava
或MultiMap
不是一种选择。
我有一个班级
public class Alpha
{
String company;
int local;
String title;
}
我有这个类的许多实例(按数百万的顺序)。我需要处理它们,最后找到独特的和重复的。 e.g。
instance --> instance1, instance5, instance7 (instance1 has instance5 and instance7 as duplicates)
instance2 --> instance2 (no duplicates for instance 2)
我的代码工作正常
声明数据结构
HashMap<Alpha,ArrayList<Alpha>> hashmap = new HashMap<Alpha,ArrayList<Alpha>>();
添加实例
for (Alpha x : arr)
{
ArrayList<Alpha> list = hashmap.get(x); ///<<<<---- doubt about this. comment#1
if (list == null)
{
list = new ArrayList<Alpha>();
hashmap.put(x, list);
}
list.add(x);
}
打印实例及其副本。
for (Alpha x : hashmap.keySet())
{
ArrayList<Alpha> list = hashmap.get(x); //<<< doubt about this. comment#2
System.out.println(x + "<---->");
for(Alpha y : list)
{
System.out.print(y);
}
System.out.println();
}
问题:我的代码有效,但为什么?当我做hashmap.get(x);
时(代码中的注释#1)。两个不同的实例可能具有相同的哈希码。在这种情况下,我将向同一个List添加2个不同的对象。
当我检索时,我应该得到一个包含2个不同实例的List。 (注释#2)当我遍历列表时,我应该看到至少一个不与密钥重复但仍然存在于列表中的实例。我没有。为什么?。我尝试从hashCode
函数返回常量值,它工作正常。
如果您想查看我对equals
和hashCode
的实施情况,请与我们联系。
奖金问题:有什么方法可以优化它?
编辑:
@Override
public boolean equals(Object obj) {
if (obj==null || obj.getClass()!=this.getClass())
return false;
if (obj==this)
return true;
Alpha guest = (Alpha)obj;
return guest.getLocal()==this.getLocal()
&& guest.getCompany() == this.getCompany()
&& guest.getTitle() == this.getTitle();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (title==null?0:title.hashCode());
result = prime * result + local;
result = prime * result + (company==null?0:company.hashCode());
return result;
}
答案 0 :(得分:3)
两个不同的实例可能具有相同的哈希码
是的,但hashCode
方法用于标识存储元素的索引。两个或多个密钥可以具有相同的hashCode
,但这也是使用equals
进行评估的原因。
来自Map#containsKey
javadoc:
如果此映射包含指定键的映射,则返回
true
。更正式的是,当且仅当此映射包含关键字k的映射(true
)时才返回key==null ? k==null : key.equals(k)
。 (最多可以有一个这样的映射。)
您当前代码的一些增强功能:
Map
并按HashMap
对其进行实例化。与List
和ArrayList
类似。通常使用String
方法比较Object
和equals
。 ==
比较引用,equals
比较Object
中存储的数据,具体取决于此方法的实现。因此,请更改Alpha#equals
中的代码:
public boolean equals(Object obj) {
if (obj==null || obj.getClass()!=this.getClass())
return false;
if (obj==this)
return true;
Alpha guest = (Alpha)obj;
return guest.getLocal().equals(this.getLocal())
&& guest.getCompany().equals(this.getCompany())
&& guest.getTitle().equals(this.getTitle());
}
在成对浏览地图的所有元素时,请改用Map#entrySet
,您可以保存 Map#get
使用的时间(因为它应该是是O(1)你不会保存那么多,但它更好):
for (Map.Entry<Alpha, List<Alpha>> entry : hashmap.keySet()) {
List<Alpha> list = entry.getValuee();
System.out.println(entry.getKey() + "<---->");
for(Alpha y : list) {
System.out.print(y);
}
System.out.println();
}
答案 1 :(得分:1)
使用
equals
和hashCode
来解决碰撞状态。
步骤:
hashCode()
equals()
以解决碰撞状态。示例代码
class Alpha {
String company;
int local;
String title;
public Alpha(String company, int local, String title) {
this.company = company;
this.local = local;
this.title = title;
}
@Override
public int hashCode() {
return title.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Alpha) {
return this.company.equals(((Alpha) obj).company);
}
return false;
}
}
...
Map<Alpha, ArrayList<Alpha>> hashmap = new HashMap<Alpha, ArrayList<Alpha>>();
hashmap.put(new Alpha("a", 1, "t1"), new ArrayList<Alpha>());
hashmap.put(new Alpha("b", 2, "t1"), new ArrayList<Alpha>());
hashmap.put(new Alpha("a", 3, "t1"), new ArrayList<Alpha>());
System.out.println("Size : "+hashmap.size());
输出
Size : 2