This is probably a trivial question but I'm having some problems (Probably due to my lack of knowledge and experience and I can't seem to find example code anywhere as I'm not too sure what to search for).
I have a list of Custom objects, List<StackTrace>. I want to remove all duplicate objects from this list based only on two properties firstLineOfStackTrace and typeOfException.
I asked a similar question the other day and someone mentioned about overriding equals and hashCode. I did a bit of research and I think I have done that now.
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((firstLineOfStackTrace == null) ? 0 : firstLineOfStackTrace.hashCode());
result = prime * result + ((typeOfexception == null) ? 0 : typeOfexception.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
LogEntry other = (LogEntry) obj;
if (firstLineOfStackTrace == null) {
if (other.firstLineOfStackTrace != null)
return false;
} else if (!firstLineOfStackTrace.equals(other.firstLineOfStackTrace))
return false;
if (typeOfexception == null) {
if (other.typeOfexception != null)
return false;
} else if (!typeOfexception.equals(other.typeOfexception))
return false;
return true;
}
My question is how do I actually use these overridden methods in my code to give me an output which has no duplicates?
I'm using Java 6. I can't figure out why "retainAll" is not correctly computing the intersection of two sets. I have
for (ProductDto dtoProd : dto.getProducts())
{
System.out.println("dtoProd:" + dtoProd.getId());
} // for
for (ProductDto princProd : principal.getProducts())
{
System.out.println("princProd:" + princProd.getId());
} // for
dto.getProducts().retainAll(principal.getProducts());
Despite the fact I observe through my System.out's that I have the same products in both sets, after, the last call, my "dto.getProducts()" is empty. This is the relevant object's id and hashcode methods, if that matters ....
#Override
public int hashCode()
{
return this.id != null ? this.id.hashCode() : 0;
}
#Override
public boolean equals(Object obj)
{
boolean ret = false;
if (obj instanceof ProductDto)
{
final ProductDto other = (ProductDto) obj;
ret = (this.id == other.getId() || (this.id != null && this.id.equals(other.getId())));
}
return ret;
}
and here is the System.out info
dtoProd:777
dtoProd:778
dtoProd:110074257z
princProd:777
princProd:777SB
princProd:110074257z
princProd:110074258z
princProd:110074259z
princProd:6161
princProd:778
What else do I need to do to compute the correct intersection?
This question already has answers here:
What issues should be considered when overriding equals and hashCode in Java?
(11 answers)
Closed 7 years ago.
Create the hashCode and equals method for the following class.
private static class MyOb {
private String name;
private Integer quality;
private final int MAXIMUM = 23;
}
I could not solve this question
Java class has default hashCode and equals method method implemented through super class. If u want to over ride them u can by following:
class MyOb {
private String name;
private Integer quality;
private final int MAXIMUM = 23;
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((quality == null) ? 0 : quality.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MyOb other = (MyOb) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (quality == null) {
if (other.quality != null)
return false;
} else if (!quality.equals(other.quality))
return false;
return true;
}
}
Note: class cannot be private or static
if you want see hash code of class.
create object
Myob myObject=new Myob();
System.out.println(myObject);
if want to equals method
myObject.equals(which one you want to campare);
I have two sets which contain some elements as object. I want to remove common element from the set. How can I remove common elements from set?
Set<AcceptorInventory> updateList = new HashSet<AcceptorInventory>();
Set<AcceptorInventory> saveList = new HashSet<AcceptorInventory>();
Both sets have some items, the saveList have duplicated items & I wish to remove duplicated items from saveList. I tried with foreach loop, but it did not work.
Sample output:
save 5
save 20
save 50
save 10
update 5
update 10
update 20
AcceptorInventory Hashcode and equals
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + count;
result = prime * result
+ ((currency == null) ? 0 : currency.hashCode());
result = prime * result + ((date == null) ? 0 : date.hashCode());
result = prime * result + (int) (id ^ (id >>> 32));
result = prime * result + (isCleared ? 1231 : 1237);
result = prime * result
+ ((kioskMachine == null) ? 0 : kioskMachine.hashCode());
result = prime * result + ((time == null) ? 0 : time.hashCode());
long temp;
temp = Double.doubleToLongBits(total);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AcceptorInventory other = (AcceptorInventory) obj;
if (count != other.count)
return false;
if (currency == null) {
if (other.currency != null)
return false;
} else if (!currency.equals(other.currency))
return false;
if (date == null) {
if (other.date != null)
return false;
} else if (!date.equals(other.date))
return false;
if (id != other.id)
return false;
if (isCleared != other.isCleared)
return false;
if (kioskMachine == null) {
if (other.kioskMachine != null)
return false;
} else if (!kioskMachine.equals(other.kioskMachine))
return false;
if (time == null) {
if (other.time != null)
return false;
} else if (!time.equals(other.time))
return false;
if (Double.doubleToLongBits(total) != Double
.doubleToLongBits(other.total))
return false;
return true;
}
updateList.removeAll(saveList);
would remove from updateList all the elements of saveList.
If you also want to remove from saveList the elements of updateList, you'll have to create a copy of one of the sets first :
Set<AcceptorInventory> copyOfUpdateList = new HashSet<>(updateList);
updateList.removeAll (saveList);
saveList.removeAll (copyOfUpdateList);
Note that in order for your AcceptorInventory to function properly as an element of a HashSet it must override the equals and hashCode methods, and any two AcceptorInventory which are equal must have the same hashCode.
You can remove common items from current saveList using
saveList.removeAll(updateList);
I have a bean with 4 attributes:
user
institutionId
groupId
postingDate
I use Eclipse to generate equals and hashcode but the resulting code is not pretty. Is there a compact way to do the same? Assuming I want equals & hashcode to use all the attributes or a subset of them.
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((groupId == null) ? 0 : groupId.hashCode());
result = prime * result + ((institutionId == null) ? 0 : institutionId.hashCode());
result = prime * result + ((postingDate == null) ? 0 : postingDate.hashCode());
result = prime * result + ((user == null) ? 0 : user.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ManGroupKey other = (ManGroupKey) obj;
if (groupId == null) {
if (other.groupId != null)
return false;
} else if (!groupId.equals(other.groupId))
return false;
if (institutionId == null) {
if (other.institutionId != null)
return false;
} else if (!institutionId.equals(other.institutionId))
return false;
if (postingDate == null) {
if (other.postingDate != null)
return false;
} else if (!postingDate.equals(other.postingDate))
return false;
if (user == null) {
if (other.user != null)
return false;
} else if (!user.equals(other.user))
return false;
return true;
}
In Java 7
public int hashCode() {
return Objects.hash(groupId, institutionId, postingDate, user);
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
// cast to correct class
Target o = (Target)obj;
return Objects.equals(groupId, o.groupId) &&
Objects.equals(institutionId, o.institutionId) &&
Objects.equals(postingDate, o.postingDate) &&
Objects.equals(user, o.user);
}
You could compact the code down, but the odds are far higher that you would introduce bugs than that you would do anything useful. All the parts of the equals and hash code method are there for a reason.
If it's bothering you most IDEs have a folding editor, just click the little yellow box (usually) and all the contents of the method get hidden away.
Instead of using the eclipse generated code, you can use Apache-common-langs(http://commons.apache.org/proper/commons-lang/) class HashCodeBuilder and EqualsBuilder to do this:
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this);
}
hashCode:
Either:
#Override
public int hashCode() {
return Objects.hash(user, institutionId, groupId, postingDate);
}
Or:
#Override
public int hashCode() {
int result = 17;
result = 31 * result + Objects.hashCode(user);
result = 31 * result + Objects.hashCode(institutionId);
result = 31 * result + Objects.hashCode(groupId);
result = 31 * result + Objects.hashCode(postingDate);
return result;
}
Equals:
public boolean equals(Object obj){
if (obj == this){
return true;
}
if (! (obj instanceof ManGroupKey)){
return false;
}
ManGroupKey other = (ManGroupKey) obj;
return Objects.equals(user, other.user)
&& Objects.equals(institutionId, other.institutionId)
&& Objects.equals(groupId, other.groupId)
&& Objects.equals(postingDate, other.postingDate);
}
You can at least remove one level of nesting by removing the other.x != null check.
Comparing a value in this way: x.equals(y) will always return false when y is null.
Aside from that: the .equals() method is a good example where a bit of reflection can be handy, possible extracted out into a generic utility method. All you have to do is run through the different fields and see if they're equal in the two objects, that can be done in a few lines.
Obviously that is only feasible when you actually want to compare each field (or you'll have to add some additions to it which let you choose the fields).
I think the library, that can suite you is apache common. It provides EqualsBuilder and HashCodeBuilder classes, that do exactly what you are looking for.
Consider this question for details: Apache Commons equals/hashCode builder
Here are some code snippets:
public class Bean{
private String name;
private int length;
private List<Bean> children;
#Override
public int hashCode(){
return new HashCodeBuilder()
.append(name)
.append(length)
.append(children)
.toHashCode();
}
#Override
public boolean equals(final Object obj){
if(obj instanceof Bean){
final Bean other = (Bean) obj;
return new EqualsBuilder()
.append(name, other.name)
.append(length, other.length)
.append(children, other.children)
.isEquals();
} else{
return false;
}
}
}