2013-07-23 14 views
5

ho una mappa con i valori duplicati:Rimuovere i valori duplicati di HashMap in Java

("A", "1"); 
("B", "2"); 
("C", "2"); 
("D", "3"); 
("E", "3"); 

Vorrei la mappa di avere

("A", "1"); 
("B", "2"); 
("D", "3"); 

Sapete come sbarazzarsi del duplicato valori?

Al momento, viene visualizzato l'errore 'java.util.ConcurrentModificationException'.

Grazie.

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); 
} 
+4

Perché mantieni il 'B' e tralasciamo' C'? Ricorda, 'HashMap' non mantiene l'ordine degli elementi inseriti. –

+0

Puoi dire esattamente il requisito? Sembra che tu voglia valori unici. HashMap può darti chiavi uniche. Invertendo la chiave e il valore sarà sufficiente per te? – midhunhk

+0

@RohitJain +1 Questa è la domanda! – NINCOMPOOP

risposta

3

ConcurrentModificationException accadendo, perché si sta rimuovendo dal map

if (value.equals(nextValue)) { 
      map.remove(key); 
     } 

è necessario rimuovere dal iterator

if (value.equals(nextValue)) { 
      keyIter.remove(key); 
     } 

Venendo alla questione voce duplicata, la sua abbastanza semplice: Find duplicate values in Java Map?

+3

Beh, se vedi chiaramente il suo codice, questo non risolverà il suo problema. –

+0

Questo codice è sbagliato, non verrà compilato e non risolverà il problema. – NINCOMPOOP

+0

@TheNewIdiot Posso saperlo ?? In modo che io possa modificare il mio post. –

4

crea una HashMap inversa!

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.add(value, key); 
} 

ora che hai hashMap devi invertirlo o stamparlo.

in ogni caso non eliminare durante l'iterazione di hashMap. salvare i valori in un elenco ed eliminarli in un ciclo esterno

+3

Rimarrà comunque casuale quale elemento verrà mantenuto (perché l'ordine di un 'HashMap' non è definito), ma se questo non è un problema, funziona bene. –

+1

@Heuster sono d'accordo, ma non ha detto che si tratta di un problema –

1

Se questo è tuo requisito frequente allora DualHashBidiMap calss di apache di commons.collections vi aiuterà di più invece di utilizzare HashMap.

0

Questo può essere fatto facilmente inserendo la tua hashmap in arraylist. Questo arraylist è di tipo hashmap.

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

     } 

Ora Stampa tua arraylist ... tutti i valori duplicati dalla hashmap facilmente rimosso ... Questo è il modo più semplice per rimuovere duplicacy

0

Questo sarà utile per rimuovere i valori duplicati di mappa.

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

uscita:

mymap: {1 = Uno, 2 = due, 4 = Tre}

0
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); 
} 
4
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(); 
     } 
    } 
2

Supponendo che si utilizza Java 8, potrebbe essere fatto utilizzando la Stream API con un Set<String> che memorizzerà i valori esistenti:

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

uscita:

Before: {A=1, B=2, C=2, D=3, E=3} 
After: {A=1, B=2, D=3} 

NB: A rigor di termini un predicato di un filtro non dovrebbe essere stateful, dovrebbe essere apolidi come detto nella javadoc al fine di garantire che il risultato rimangono deterministico e corretto anche se utilizziamo un flusso parallelo. Tuttavia qui, presumo che non si intende utilizzare un flusso parallelo in modo tale che questo approccio rimanga valido.

+0

In realtà, gli stream non dovrebbero essere utilizzati con un filtro che ha effetto collaterale. –

+0

@GraemeMoss è giusto, ho aggiunto un commento per evitare l'abuso/incomprensione –

0

Questo può essere fatto utilizzando Java 8. È necessario il concetto di flusso. Lo pseudocodice, è stream(). Filter(). Collect(). Se la mappa iniziale: {A = 1, B = 2, C = 2, D = 3, E = 3}. Quindi la risposta richiesta dopo aver rimosso i duplicati è {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); 

    } 
} 
Problemi correlati