如何在下面的代码中获取唯一的对象数组列表:
import java.util.*;
class t1 {
public static void main(String[] args) {
Object[] o1 = new Object[] { null, "abc@aaa.com", "ENG", "775778435", 1};
Object[] o2 = new Object[] { null, "abc@aaa.com", "ENG", "775778435", 1};
List<Object[]> result = new ArrayList<Object[]>();
result.add(o1);
result.add(o2);
// The above result list is coming from some DB & I cannot change the structure of above script.
// Now, I need to remove the duplicates from this result list meaning I need to find duplicates from the objects within the list.
// I tried below code but it still prints duplicates. Any help???
Set<User> setResult = new HashSet<User>();
User userInfo = null;
for (Object[] userData : result) {
userInfo = new User((String)userData[0], (String)userData[1], (String)userData[2], (String)userData[3], (Integer) userData[4]);
setResult.add(userInfo);
}
Iterator it = setResult.iterator();
while (it.hasNext()) {
Object o = it.next();
User u = (User) o;
System.out.println("non-duplicate = " + u.getEmail());
}
// Expected result: non-duplicate = abc@aaa.com
// Actual result: non-duplicate = abc@aaa.com getting printed twice i.e. duplicate not getting removed!
}
}
class User {
public String firstName;
public String email;
public String language;
public String productCode;
public int status;
public User() {
}
public User(String fName, String userId, String lang, String productCode, int status) {
this.firstName = fName;
this.email = userId;
this.language = lang;
this.productCode = productCode;
this.status = status;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String getProductCode() {
return productCode;
}
public void setProductCode(String productCode) {
this.productCode = productCode;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
@Override
public int hashCode() {
int fNameHash = 0;
int lNameHash = 0;
int emailHash = 0;
int langHash = 0;
int productCodeHash = 0;
if (this.firstName != null) {
fNameHash = this.firstName.hashCode();
}
if (this.email != null) {
emailHash = this.email.hashCode();
}
if (this.language != null) {
langHash = this.language.hashCode();
}
if (this.productCode != null) {
productCodeHash = this.productCode.hashCode();
}
return (fNameHash + lNameHash + emailHash + langHash + productCodeHash + this.status);
}
@Override
public boolean equals(Object obj) {
if(obj != null && obj instanceof User) {
User temp = (User) obj;
if (this.firstName != null && temp.firstName != null && this.firstName.equalsIgnoreCase(temp.firstName)
&& this.email != null && temp.email != null && this.email.equalsIgnoreCase(temp.email)
&& this.language != null && temp.language != null && this.language.equalsIgnoreCase(temp.language)
&& this.productCode != null && temp.productCode != null && this.productCode.equalsIgnoreCase(temp.productCode)
&& this.status == temp.status) {
return true;
}
}
return false;
}
}
我的预期结果是打印abc@aaa.com一次,但打印两次!!
任何人都可以告诉我如何更正此代码吗?
谢谢!
答案 0 :(得分:2)
问题是您的User.equals
会预测会返回false
,因为这两个实例都有null
firstName
s:
if (this.firstName != null && temp.firstName != null && this.firstName.equalsIgnoreCase(temp.firstName)
因此,即使它们具有相同的hashCode
,它也仅仅被视为碰撞而不是匹配,因为equals
已被破坏。
尝试纠正:-)用......之类的东西替换逻辑。
firstName == temp.firstName || firstName != null && firstName.equalsIgnoreCase(temp.firstName)
......应该有效; - )
您可以看到完整的版本here。
顺便说一句,您忘了在lNameHash
中分配User.hashCode
。
答案 1 :(得分:1)
您的equals
方法和hashcode
方法都未正确实施。
equals
个成员时,您的false
方法会返回null
。hashCode
的实现可以为某些比较相等的对象返回不同的哈希码。您必须提供equals
和hashCode
的正确实施才能在HashSet
中使用您的对象。
答案 2 :(得分:0)
问题在于firstName值对于两个对象都为null。因此,equals()方法返回false,Set
将您的对象视为不同。
尝试使用以下内容更改您的equals和hashcode:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof User)) return false;
User user = (User) o;
if (status != user.status) return false;
if (email != null ? !email.equals(user.email) : user.email != null) return false;
if (firstName != null ? !firstName.equals(user.firstName) : user.firstName != null) return false;
if (language != null ? !language.equals(user.language) : user.language != null) return false;
if (productCode != null ? !productCode.equals(user.productCode) : user.productCode != null) return false;
return true;
}
@Override
public int hashCode() {
int result = firstName != null ? firstName.hashCode() : 0;
result = 31 * result + (email != null ? email.hashCode() : 0);
result = 31 * result + (language != null ? language.hashCode() : 0);
result = 31 * result + (productCode != null ? productCode.hashCode() : 0);
result = 31 * result + status;
return result;
}
最好的方法是按照另一个答案中的建议,从IDE生成等号和哈希码。