Reputation: 11
I use a map in both outer and inner loop and I need to delete an entry in the map in the inner loop so that the deleted entry is not iterated in the outer or inner loop anymore.
I tried remove() on the inner iterator but that does leads to an exception when iterating further on the outer loop.
Map<String, String> testMap = new HashMap<>();
testMap.put("A", "AAA");
testMap.put("B", "BBB");
testMap.put("C", "CCC");
testMap.put("D", "DDD");
for(Iterator<Map.Entry<String, String>> it = testMap.entrySet().iterator(); it.hasNext();) {
Map.Entry<String, String> outerEntry = it.next();
for(Iterator<Map.Entry<String, String>> it1 = testMap.entrySet().iterator(); it1.hasNext();) {
Map.Entry<String, String> innerEntry = it1.next();
if(!outerEntry.getKey().equals(innerEntry.getKey()) && !innerEntry.getKey().equals("D")) {
// it1.remove();
// remove entries "B" and "C" from testMap so that the next iteration in outer loop is "D"
// also I don't require the entries "B" and "C" in the inner loop once they are deleted
}
}
}
In the code given, the entries "B" and "C" must be deleted from the testMap on the first iteration of outer loop. The next iterator of outer loop should be of "D".
Purpose of the code is to collect Map entries which have same values.
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Arrays;
import java.util.Set;
import java.util.HashSet;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args)
{
Map<String, Map<String, List<String>>> resultMap = new HashMap<>();
Map<String, List<String>> testMap = new HashMap<>();
testMap.put("A", new ArrayList<>(Arrays.asList("AAA", "CCC", "BBB")));
testMap.put("B", new ArrayList<>(Arrays.asList("AAA", "BBB", "CCC")));
testMap.put("C", new ArrayList<>(Arrays.asList("CCC")));
testMap.put("D", new ArrayList<>(Arrays.asList("DDD")));
testMap.put("E", new ArrayList<>(Arrays.asList("DDD")));
testMap.put("F", new ArrayList<>(Arrays.asList("AAA", "BBB", "CCC")));
// process testMap in a way that resultMap contains
// <A, <G1, [AAA, BBB, CCC]>>
// <B, <G1, [AAA, BBB, CCC]>>
// <C, <G2, [CCC]>>
// <D, <G3, [DDD]>>
// <E, <G3, [DDD]>>
// <F, <G1, [AAA, BBB, CCC]>>
// here G1, G2, G3 are groups that are created which represents testMap entries that have same values.
// in resultMap, the order of [AAA, BBB, CCC] doesn't matter
String gName = "G";
int gId = 0;
for(Map.Entry<String, List<String>> entry : testMap.entrySet()) {
if (resultMap.containsKey(entry.getKey())) {
continue;
}
++gId;
String group = gName + String.valueOf(gId);
Set<String> entryValuesSet = new HashSet<>(entry.getValue());
Map<String, List<String>> groupEntries = new HashMap<>();
groupEntries.put(group, entry.getValue());
Set<String> groupSet = testMap.entrySet().stream().filter(e -> !resultMap.containsKey(e.getKey()) && new HashSet(e.getValue()).equals(entryValuesSet)).map(f -> f.getKey()).collect(Collectors.toSet());
// here is my problem.
// Even though in the first iteration (entry "A") itself, entries "A", "B", "F" have assigned a group
// they are still being checked on further iterations (entries "C", "D") and need a filter condition to exclude
// which are really unnecessary checks if I could just delete those entries
for (String g : groupSet) {
resultMap.put(g, groupEntries);
}
}
System.out.println(resultMap);
}
}
Is there a way to delete the entries in testMap that have already assigned in a group so that the unwanted checks can be avoided?
Upvotes: 0
Views: 219
Reputation: 10959
Following on from @Jordans comment:
The problem you have with your current code is that the first iteration by the innerloop removes B
and C
then the outer loop is expecting to encounter B
next but that has been removed.
You could do this by using a list to determine the entries to be removed similar to below.
Map<String, String> testMap = new HashMap<>();
testMap.put("A", "AAA");
testMap.put("B", "BBB");
testMap.put("C", "CCC");
testMap.put("D", "DDD");
System.out.println(testMap);
List<Map.Entry<String, String>> removedInnerEntries = new ArrayList<>();
for(Map.Entry<String, String> outer : testMap.entrySet()){
if(removedInnerEntries.contains(outer))
continue;
System.out.println("OuterLoop:" + outer);
for(Map.Entry<String, String> inner : testMap.entrySet()) {
System.out.println("InnerLoop:" + inner);
if (!outer.getKey().equals(inner.getKey()) &&
!inner.getKey().equals("D") &&
!removedInnerEntries.contains(inner)) {
System.out.println(" Remove :" + inner);
removedInnerEntries.add(inner);
}
}
}
removedInnerEntries.forEach(e -> testMap.remove(e.getKey(), e.getValue()));
System.out.println(testMap);
However, if you run this you will notice that this is not quite right as on the last iteration A
get removed as it fails the first condition !outer.getKey().equals(inner.getKey())
of the inner loop, so you would also need to fix that.
Alternatively you could create your own iterator to do this.
Upvotes: 0