[英]Correct way to implement Map<MyObject,ArrayList<MyObject>>
I was asked this in interview. 面试中有人问我这个问题。 using
Google Guava
or MultiMap
is not an option. 不能使用
Google Guava
或MultiMap
。 I have a class 我有一堂课
public class Alpha
{
String company;
int local;
String title;
}
I have many instances of this class (in order of millions). 我有很多此类的实例(以百万计)。 I need to process them and at the end find the unique ones and their duplicates.
我需要处理它们,最后找到唯一的及其重复项。 eg
例如
instance --> instance1, instance5, instance7 (instance1 has instance5 and instance7 as duplicates)
instance2 --> instance2 (no duplicates for instance 2)
My code works fine 我的代码工作正常
declare datastructure 声明数据结构
HashMap<Alpha,ArrayList<Alpha>> hashmap = new HashMap<Alpha,ArrayList<Alpha>>();
Add instances 添加实例
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);
}
Print instances and their duplicates. 打印实例及其副本。
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();
}
Question: My code works, but why? 问题:我的代码有效,但是为什么呢? when I do
hashmap.get(x);
当我做
hashmap.get(x);
(comment#1 in code). (代码中的注释1)。 it is possible that two different instances might have same hashcode.
两个不同的实例可能具有相同的哈希码。 In that case, I will add 2 different objects to the same List.
在这种情况下,我将2个不同的对象添加到同一List。
When I retrieve, I should get a List which has 2 different instances. 当我检索时,我应该得到一个包含2个不同实例的列表。 (comment#2) and when I iterate over the list, I should see at least one instance which is not duplicate of the key but still exists in the list.
(评论2),当我遍历列表时,我应该看到至少一个实例,该实例不是键的重复项,但仍存在于列表中。 I don't.
我不。 Why?.
为什么?。 I tried returning constant value from my
hashCode
function, it works fine. 我尝试从我的
hashCode
函数返回常量值,它工作正常。
If you want to see my implementation of equals
and hashCode
,let me know. 如果要查看我的
equals
和hashCode
,请告诉我。
Bonus question: Any way to optimize it? 奖励问题:有什么优化方法吗?
Edit: 编辑:
@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;
}
it is possible that two different instances might have same hashcode
两个不同的实例可能具有相同的哈希码
Yes, but hashCode
method is used to identify the index to store the element. 是的,但是
hashCode
方法用于标识存储元素的索引。 Two or more keys could have the same hashCode
but that's why they are also evaluated using equals
. 两个或更多键可能具有相同的
hashCode
但这就是为什么还要使用equals
对其进行评估的原因。
From Map#containsKey
javadoc: 从
Map#containsKey
javadoc:
Returns
true
if this map contains a mapping for the specified key.如果此映射包含指定键的映射,则返回
true
。 More formally, returnstrue
if and only if this map contains a mapping for a key k such that (key==null ? k==null : key.equals(k)
).更正式地讲,当且仅当此映射包含键k的映射(
key==null ? k==null : key.equals(k)
)时,返回true
。 (There can be at most one such mapping.)(最多可以有一个这样的映射。)
Some enhancements to your current code: 当前代码的一些增强功能:
Map
and instantiate it by HashMap
. Map
并通过HashMap
实例化它。 Similar to List
and ArrayList
. List
和ArrayList
。 Compare String
s and Object
s in general using equals
method. 通常使用
equals
方法比较String
和Object
。 ==
compares references, equals
compares the data stored in the Object
depending the implementation of this method. ==
比较引用, equals
根据此方法的实现比较存储在Object
的数据。 So, change the code in Alpha#equals
: 因此,更改
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()); }
When navigating through all the elements of a map in pairs, use Map#entrySet
instead, you can save the time used by Map#get
(since it is supposed to be O(1) you won't save that much but it is better): 成对浏览地图的所有元素时,请改用
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(); }
Use
equals
along withhashCode
to solve the collision state.将
equals
与hashCode
一起使用以解决冲突状态。
Steps: 脚步:
hashCode()
hashCode()
的标题进行比较 equals()
based on company name to resolve the collision state. equals()
以解决冲突状态。 Sample code 样例代码
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());
Output 产量
Size : 2
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.