2013-07-23 5 views
5

У меня есть карта с повторяющимися значениями:Удалить повторяющиеся значения из HashMap в Java

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

Я хотел бы карту, чтобы иметь

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

Вы знаете, как избавиться от дубликата значения?

В настоящее время я получаю сообщение об ошибке «java.util.ConcurrentModificationException».

спасибо.

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

Почему вы держите 'B' и оставьте' C'? Помните: 'HashMap' не поддерживает порядок вставленных элементов. –

+0

Можете ли вы сказать точное требование? Похоже, вы хотите уникальные ценности. HashMap может предоставить вам уникальные ключи. Будет ли инвертировать ключ и значение для вас достаточно? – midhunhk

+0

@RohitJain +1 Вот в чем вопрос! – NINCOMPOOP

ответ

3

ConcurrentModificationException происходит, потому что вы удаляете из map

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

Вы должны удалить из iterator

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

Приходя к дубликата вопроса входа, Его довольно просто: Find duplicate values in Java Map?

+3

Хорошо, если вы ясно видите его код, это не решит его проблему. –

+0

Этот код неверен, он не будет компилироваться и не решает проблему. – NINCOMPOOP

+0

@ TheNewIdiot Могу я знать, что? Так что я отредактирую свой пост. –

4

сделать обратный 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.add(value, key); 
} 

Теперь, когда у вас есть hashMap, вам необходимо изменить его или распечатать.

в любом случае не удалить во время итерации hashMap. сохранить значения в списке и удалить их во внешнем контуре

+3

Будет по-прежнему случайным, какой элемент будет сохранен (поскольку порядок 'HashMap' не определен), но если это не проблема, это отлично работает. –

+1

@ Хозяин я согласен, но он не сказал, что это проблема –

1

Если это ваше частое требование тогда DualHashBidiMap Calss из апача commons.collections поможет вам больше, вместо того, чтобы использовать HashMap.

0

Это легко сделать, помещая ваш хэш-карту в arraylist. Этот arraylist имеет тип 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); 
       } 
      } 

     } 

Теперь распечатайте ArrayList ... все повторяющиеся значения из HashMap легко удаляется ... Это самый простой способ, чтобы удалить duplicacy

0

Это будет полезно, чтобы удалить повторяющиеся значения из карты.

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

Выход:

MyMap: {1 = один, 2 = два, 4 = Три}

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

Предполагая, что вы используете Java 8, это может быть сделано с помощью Stream API с Set<String>, который будет хранить существующие значения:

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

Выход:

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

NB: Строго говоря, предикат фильтра не должен быть состоянием, он должен быть без гражданства, как указано в javadoc для того, чтобы гарантировать, что результат остаются детерминистическими и правильно, даже если мы используем параллельный поток. Однако здесь я предполагаю, что вы не собираетесь использовать параллельный поток, чтобы этот подход оставался в силе.

+0

Строго говоря, потоки не должны использоваться с фильтром побочных эффектов. –

+0

@GraemeMoss это правильно, я добавил комментарий, чтобы избежать неправильного использования/непонимания –

0

Это может быть сделано с использованием Java 8. Понятие потока требуется. Псевдокодом является поток(). Filter(). Collect(). Если исходная карта: {A = 1, B = 2, C = 2, D = 3, E = 3}. Затем требуемый ответ после удаления дубликатов {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); 

    } 
} 
Смежные вопросы