Compare two set and remove common items - java

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);

Related

How do I use overridden HashCode and Equals on my list?

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?

Check if all values in a map are equal

I need to check if all values in a map are equal. I have a method to perform this task but would like to use a library or native methods. Limitations: Java 5 + Apache Commons libraries.
public static boolean isUnique(Map<Dboid,?> aMap){
boolean isUnique = true;
Object currValue = null;
int iteration = 0;
Iterator<?> it = aMap.entrySet().iterator();
while(it.hasNext() && isUnique){
iteration++;
Object value = it.next();
if(iteration > 1){
if (value != null && currValue == null ||
value == null && currValue != null ||
value != null && currValue != null & !value.equals(currValue)) {
isUnique = false;
}
}
currValue = value;
}
return isUnique;
}
What about this something like this:
Set<String> values = new HashSet<String>(aMap.values());
boolean isUnique = values.size() == 1;
how about
return (new HashSet(aMap.values()).size() == 1)
I know the original questions asks for solutions in Java 5, but in case someone else searching for an answer to this question is not limited to Java 5 here is a Java 8 approach.
return aMap.values().stream().distinct().limit(2).count() < 2
You could store the values in a Bidirectional Map and always have this property.
public static boolean isUnique(Map<Dboid,?> aMap) {
Set<Object> values = new HashSet<Object>();
for (Map.Entry<Dboid,?> entry : aMap.entrySet()) {
if (!values.isEmpty() && values.add(entry.getValue())) {
return false;
}
}
return true;
}
This solution has the advantage to offer a memory-saving short cut if there are many differences in the map. For the special case of an empty Map you might choose false as return value, change it appropriately for your purpose.
Or even better without a Set (if your Map does not contain null-values):
public static boolean isUnique(Map<Dboid,?> aMap) {
Object value = null;
for (Object entry : aMap.values()) {
if (value == null) {
value = entry;
} else if (!value.equals(entry)) {
return false;
}
}
return true;
}
As my comment above:
//think in a more proper name isAllValuesAreUnique for example
public static boolean isUnique(Map<Dboid,?> aMap){
if(aMap == null)
return true; // or throw IlegalArgumentException()
Collection<?> c = aMap.getValues();
return new HashSet<>(c).size() <= 1;
}

Compact equals and hashcode

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;
}
}
}

Object equivalency in hashCode

I'm working with hashCode for the first time and not sure how to check if two objects are equal. This is what I have so far.
/** Represents a City */
class City {
/** Decimal format to print leading zeros in zip code */
static DecimalFormat zipFormat = new DecimalFormat("00000");
int zip;
String name;
String state;
double longitude;
double latitude;
/** The full constructor */
public City (int zip, String name, String state,
double longitude, double latitude) {
this.zip = zip;
this.name = name;
this.state = state;
this.longitude = longitude;
this.latitude = latitude;
}
/** to make sure the two cities have the same name, state, zip code,
* and the same latitude and longitude */
public boolean equals(Object obj){
if (obj == null)
return false;
City temp = (City)obj;
System.out.println(City.equals(obj));
}
Assuming equality in your case means all properties are same in your equals method add
City temp = (City)obj;
return this.zip == temp.zip &&
this.name == temp.name &&
...
;
eclipse auto-generates for you:
#Override
public int hashCode()
{
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(latitude);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(longitude);
result = prime * result + (int) (temp ^ (temp >>> 32));
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((state == null) ? 0 : state.hashCode());
result = prime * result + zip;
return result;
}
#Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
City other = (City) obj;
if (Double.doubleToLongBits(latitude) != Double
.doubleToLongBits(other.latitude))
return false;
if (Double.doubleToLongBits(longitude) != Double
.doubleToLongBits(other.longitude))
return false;
if (name == null)
{
if (other.name != null)
return false;
}
else if (!name.equals(other.name))
return false;
if (state == null)
{
if (other.state != null)
return false;
}
else if (!state.equals(other.state))
return false;
if (zip != other.zip)
return false;
return true;
}

Java SortedMap implemented with List of values

I want to have a Sorted map as follows:
srcAddr, dstAddr, srcPort, dstPort, protocol as keys
and a List of values as
packetLength, timeArrival for each key.
Is it possible to implement them in separate classes? I am confused if it will work this way.
Update:
I am getting an error indicating im not overriding abstract method compareTo(). Can you help me with it?
package myclassifier;
import java.io.Serializable;
import java.util.*;
public class Flows implements Serializable, Comparable {
String srcAddr, dstAddr, srcPort, dstPort, protocol;
public int compareTo(Flows other) {
int res = this.srcAddr.compareTo(other.srcAddr);
if (res != 0) {
return res;
}
res = this.dstAddr.compareTo(other.dstAddr);
if (res != 0) {
return res;
}
res = this.srcPort.compareTo(other.srcPort);
if (res != 0) {
return res;
}
res = this.dstPort.compareTo(other.dstPort);
if (res != 0) {
return res;
}
return this.protocol.compareTo(other.protocol);
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((dstAddr == null) ? 0 : dstAddr.hashCode());
result = prime * result + ((dstPort == null) ? 0 : dstPort.hashCode());
result = prime * result + ((srcAddr == null) ? 0 : srcAddr.hashCode());
result = prime * result + ((srcPort == null) ? 0 : srcPort.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;
Flows other = (Flows) obj;
if (dstAddr == null) {
if (other.dstAddr != null)
return false;
} else if (!dstAddr.equals(other.dstAddr))
return false;
if (dstPort == null) {
if (other.dstPort != null)
return false;
} else if (!dstPort.equals(other.dstPort))
return false;
if (srcAddr == null) {
if (other.srcAddr != null)
return false;
} else if (!srcAddr.equals(other.srcAddr))
return false;
if (srcPort == null) {
if (other.srcPort != null)
return false;
} else if (!srcPort.equals(other.srcPort))
return false;
return true;
}
}
You can write a, say a 'MyKey' class with srcAddr, dstAddr, srcPort, dstPort and protocol as member variables of it. You have to carefully override the equals and hashCode method of this class. Also this class has to implement the Comparable interface to indicate how your ordering will be determined based on member fields.
You can implement a class MyValue to have packetLength, timeArrival etc as members. This will be the value you want to store in your map.
Use TreeMap to store MyValue against MyKey.
you can implement different classes one for the key
public class Packet implements Serializable, Comparable {
String srcAddr, dstAddr, srcPort, dstPort;
public int compareTo(Object arg0) {
// your sorting logic here
return ...;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((dstAddr == null) ? 0 : dstAddr.hashCode());
result = prime * result + ((dstPort == null) ? 0 : dstPort.hashCode());
result = prime * result + ((srcAddr == null) ? 0 : srcAddr.hashCode());
result = prime * result + ((srcPort == null) ? 0 : srcPort.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;
Packet other = (Packet) obj;
if (dstAddr == null) {
if (other.dstAddr != null)
return false;
} else if (!dstAddr.equals(other.dstAddr))
return false;
if (dstPort == null) {
if (other.dstPort != null)
return false;
} else if (!dstPort.equals(other.dstPort))
return false;
if (srcAddr == null) {
if (other.srcAddr != null)
return false;
} else if (!srcAddr.equals(other.srcAddr))
return false;
if (srcPort == null) {
if (other.srcPort != null)
return false;
} else if (!srcPort.equals(other.srcPort))
return false;
return true;
}
}
And one for the data
public class Payload {
Integer packetLength;
Date timeArrival;
}
then when you put payload with a certain key in a sorted map it will be placed in order according to the compareTo method
You want sort your map based on its keys or values? Do you want the keys to be sorted alphabetically or in the order you've specified above? Overall it shouldn't be too difficult:
SorterMap<String, List> mySortedMap = new TreeMap<String, List>(myComparator);
mySortedMap.put("srcAddr", Arrays.asList(new Object[] {packetLengthValue, arrivalTimeValue}))
Where you should implement myComparator to sort the keys according to your requirements.

Categories

Resources