Reputation: 121
I have a map with duplicate values:
("A", "1");
("B", "2");
("C", "2");
("D", "3");
("E", "3");
I would like to the map to have
("A", "1");
("B", "2");
("D", "3");
Do you know how to get rid of the duplicate values?
At present, I get 'java.util.ConcurrentModificationException' error.
Thank you.
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<String, String>();
map.put("A", "1");
map.put("B", "2");
map.put("C", "2");
map.put("D", "3");
map.put("E", "3");
Set<String> keys = map.keySet(); // The set of keys in the map.
Iterator<String> keyIter = keys.iterator();
while (keyIter.hasNext()) {
String key = keyIter.next();
String value = map.get(key);
System.out.println(key + "\t" + value);
String nextValue = map.get(key);
if (value.equals(nextValue)) {
map.remove(key);
}
}
System.out.println(map);
}
Upvotes: 12
Views: 118794
Reputation: 1132
It can be done without mutating the original map:
public static <K,V> Map<K,V> getDistinctValues(Map<K,V> map) {
Set<V> values = new HashSet<>();
return map.entrySet().stream()
.filter(entry -> values.add(entry.getValue()))
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue
));
}
Upvotes: 0
Reputation: 11597
make a reverse HashMap!
HashMap<String, String> map = new HashMap<String, String>();
Set<String> keys = map.keySet(); // The set of keys in the map.
Iterator<String> keyIter = keys.iterator();
while (keyIter.hasNext()) {
String key = keyIter.next();
String value = map.get(key);
map.put(value, key);
}
now that you have the hashMap you need reverse it or print it.
in anyway do not delete while iterating hashMap. save the values in a list and delete them in an outer loop
Upvotes: 9
Reputation: 436
If you are looking just to remove the concurrentModification exception, then just replace your HashMap with ConcurrentHashMap.
To know more about ConcurrentHashMap look here
Upvotes: 0
Reputation: 2152
This can be done using Java 8. The concept of stream is required. The pseudocode, is stream().filter().collect(). If the Initial Map : {A=1, B=2, C=2, D=3, E=3}. Then the required answer after removing the duplicates is {A=1, B=2, D=3} .
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class RemoveDuplicates1 {
public static void main(String[] args) {
//Initial Map : {A=1, B=2, C=2, D=3, E=3}
//After => {A=1, B=2, D=3}
Map<String , String > map = new HashMap<>();
map.put("A", "1");
map.put("B", "2");
map.put("C", "2");
map.put("D", "3");
map.put("E", "3");
System.out.printf("before : " +map );
System.out.println("\n");
Set<String> set = new HashSet<>();
map = map.entrySet().stream()
.filter(entry -> set.add(entry.getValue()))
.collect(Collectors.toMap(Map.Entry :: getKey , Map.Entry :: getValue));
System.out.printf("after => " + map);
}
}
Upvotes: 3
Reputation: 45005
Assuming that you use Java 8, it could be done using the Stream API
with a Set<String>
that will store the existing values:
Map<String, String> map = new HashMap<>();
map.put("A", "1");
...
System.out.printf("Before: %s%n", map);
// Set in which we keep the existing values
Set<String> existing = new HashSet<>();
map = map.entrySet()
.stream()
.filter(entry -> existing.add(entry.getValue()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
System.out.printf("After: %s%n", map);
Output:
Before: {A=1, B=2, C=2, D=3, E=3}
After: {A=1, B=2, D=3}
NB: Strictly speaking a predicate of a filter is not supposed to be stateful, it should be stateless as mentioned into the javadoc in order to ensure that the result remain deterministic and correct even if we use a parallel stream. However here, I assume that you don't intend to use a parallel stream such that this approach remains valid.
Upvotes: 9
Reputation: 77
Map<String,Object> mapValues = new HashMap<String,Object>(5);
mapValues.put("1", "TJ");
mapValues.put("2", "Arun");
mapValues.put("3", "TJ");
mapValues.put("4", "Venkat");
mapValues.put("5", "Arun");
Collection<Object> list = mapValues.values();
for(Iterator<Object> itr = list.iterator(); itr.hasNext();)
{
if(Collections.frequency(list, itr.next())>1)
{
itr.remove();
}
}
Upvotes: 5
Reputation: 61
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("A", "1");
map.put("B", "2");
map.put("C", "2");
map.put("D", "3");
map.put("E", "3");
System.out.println("Initial Map : " + map);
for (String s : new ConcurrentHashMap<>(map).keySet()) {
String value = map.get(s);
for (Map.Entry<String, String> ss : new ConcurrentHashMap<>(map)
.entrySet()) {
if (s != ss.getKey() && value == ss.getValue()) {
map.remove(ss.getKey());
}
}
}
System.out.println("Final Map : " + map);
}
Upvotes: 1
Reputation: 39
This will be helpful to remove duplicate values from map.
Map<String, String> myMap = new TreeMap<String, String>();
myMap.put("1", "One");
myMap.put("2", "Two");
myMap.put("3", "One");
myMap.put("4", "Three");
myMap.put("5", "Two");
myMap.put("6", "Three");
Set<String> mySet = new HashSet<String>();
for (Iterator itr = myMap.entrySet().iterator(); itr.hasNext();)
{
Map.Entry<String, String> entrySet = (Map.Entry) itr.next();
String value = entrySet.getValue();
if (!mySet.add(value))
{
itr.remove();
}
}
System.out.println("mymap :" + mymap);
Output:
mymap :{1=One, 2=Two, 4=Three}
Upvotes: 0
Reputation: 2289
This can be easily done by putting your hashmap into arraylist. This arraylist is of hashmap type.
ArrayList<HashMap<String, String>> mArrayList=new ArrayList<>();
HashMap<String, String> map=new HashMap<>();
map.put("1", "1");
mArrayList.add(map);
map=new HashMap<>();
map.put("1", "1");
mArrayList.add(map);
map=new HashMap<>();
map.put("1", "2");
mArrayList.add(map);
map=new HashMap<>();
map.put("1", "3");
mArrayList.add(map);
map=new HashMap<>();
map.put("1", "2");
mArrayList.add(map);
for(int i=0;i<mArrayList.size();i++)
{
temp=mArrayList.get(i).get("1");
for(int k=i+1;k<mArrayList.size();k++)
{
if(temp.equals(mArrayList.get(k).get("1")))
{
mArrayList.remove(k);
}
}
}
Now print your arraylist...all the duplicate values from the hashmap easily removed...This is the easiest way to remove duplicacy
Upvotes: 0
Reputation: 8483
If this is yours frequent requirement then DualHashBidiMap
calss of apache's commons.collections will help you more instead of using HashMap
.
Upvotes: 1
Reputation: 122026
ConcurrentModificationException
happening,because you are removing from map
if (value.equals(nextValue)) {
map.remove(key);
}
You have to remove from iterator
if (value.equals(nextValue)) {
keyIter.remove(key);
}
Coming to the duplicate entry issue,Its pretty simple :Find duplicate values in Java Map?
Upvotes: 2