Problem in java.util.Set.addAll() method
I have a java.util.Set<City> cities
and I need to add cities to this set in 2 ways:
By adding individual city (with the help of
cities.add(city)
method call)By adding another set of cities to this set (with the help of
cities.addAll(anotherCitiesSet)
method call)
开发者_开发百科But the problem in second approach is that i don't know whether there were any duplicate cities in the anotherCitiesSet
.
I want to do some processing whenever a duplicate entry is tried to be entered in thecities
set.
Copy the cities
set (to say, citiesCopy
), and then call citiesCopy.retainAll(anotherCitiesSet)
- the resulting set in citiesCopy
will contain the intersection of the two sets, thus allowing you to easily see which cities are duplicated, if any.
Alternatively, loop through the second set and manually add each of the elements, checking the return value from add()
each time:
for(java.util.Set<City> c : anotherCitiesSet) {
if(!cities.add(c)) {
// c was a duplicate, do something?
}
}
is your city just String (tho it is object) or it is object containing other stuffs?
if String, then I guess above answers will work.
if it is object containing things like : String name, int population, etc... And you only want to compare String name to remove duplicates, then you can use {HashSet} class and override its (HashCode) and (equals) methods.
because you may have two cities: NYC, and another NYC. containing the same info. but since they are two objects in heap. they will have different HashCode. There say, your HashSet will keep both of them. HashSet checks both HashCode and meaning equals().
The solution is to override both methods:
class City{
String name; //if you only care city name
....
....
public boolean equals(Object myCity){ // override equals(). only look at the name.
City city2 = (City) myCity;
return this.getName().equals(city2.getName()); //String itself has a .equal() to compare
}
public int HashCode(){ // override HashCode().
return name.hashCode(); //also String itself has a .hashCode() to check equality
}
public String getName(){
return name;
}
...
...
}
Derive a class from java.util.Set, override addAll if possible (if not, create new method) and there add items one by one, and do your custom processing if you detect a duplicate entry.
You will need to check for duplicates before you call addAll
:
Set<City> cities = getCities();
Set<City> otherCities = getOtherSetOfCities();
Set<City> duplicates = new HashSet<City>(otherCities);
duplicates.retainAll(cities);
// now duplicates contains all City objects that are in otherCities and cities
Before your cities.addAll()
do:
Set<City> intersection = new HashSet<City>(cities);
cities.retainAll(anotherCitiesSet);
// Process all the items in the intersection, these are your duplicates
...
cities.addAll(anotherCitiesSet);
I believe that the most elegant solution is to use an implementation of java.util.Set
,
e.g. java.util.HashSet
.
For example, the following code adds all the integers in the set d
into the set c
,
where duplicates are not added.
Code:
import java.util.HashSet;
import java.util.LinkedList;
import com.google.common.base.Joiner;
public class CollectionsTest {
public static void main(String[] args) {
HashSet<Integer> c = new HashSet<>();
c.add(0);
c.add(1);
c.add(2);
HashSet<Integer> d = new HashSet<>();
d.add(2);
d.add(3);
System.out.println("c = " + Joiner.on(", ").join(c));
System.out.println("d = " + Joiner.on(", ").join(d));
c.addAll(d);
System.out.println("c.addAll(d) = " + Joiner.on(", ").join(c));
}
}
Output:
c = 0, 1, 2
d = 2, 3
c.addAll(d) = 0, 1, 2, 3
In order for a HashSet
to work correctly for the City
objects,
the City
objections should override the hashCode()
and equals()
methods.
Then the HashSet
will remove duplicates when using addAll()
for free!
精彩评论