Differences between iterator and for loop in hashmap - java

Below are the scenario of iterator and for loop:
1) Using iterator:
ihm.put("Zara", new Double(3434.34));
ihm.put("Mahnaz", new Double(123.22));
ihm.put("Ayan", new Double(1378.00));
ihm.put("Daisy", new Double(99.22));
ihm.put("Qadir", new Double(-19.08));
// Get a set of the entries
Set set = ihm.entrySet();
// Get an iterator
Iterator i = set.iterator();
// Display elements
while(i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
System.out.print(me.getKey() + ": ");
System.out.println(me.getValue());
}
System.out.println();
=====================================
Using For Loop:
HashMap<String, Integer> map = new HashMap<String, Integer>();
//Adding key-value pairs
map.put("ONE", 1);
map.put("TWO", 2);
map.put("THREE", 3);
map.put("FOUR", 4);
//Adds key-value pair 'ONE-111' only if it is not present in map
map.putIfAbsent("ONE", 111);
//Adds key-value pair 'FIVE-5' only if it is not present in map
map.putIfAbsent("FIVE", 5);
//Printing key-value pairs of map
Set<Entry<String, Integer>> entrySet = map.entrySet();
for (Entry<String, Integer> entry : entrySet)
{
System.out.println(entry.getKey()+" : "+entry.getValue());
}
}
In the above both cases iterator and for loop are doing the same job.So can anyone tell me what is the differences between them and when i can use iterator and for loop.

The only significant difference between loop and iterator (apart from readability) is that while using iterator you can edit content of the collection through that Iterator instance.
If you try to edit map while looping through it you will get Concurrent ModificationException
You should use iterator when you want to update map while iterating over it e.g. remove entries which match some conditions.
Iterator<Entry> it = map.iterator();
while(it.hasNext())
if(check(it.next()))
it.remove();
I have to note that for-loop is a syntactic sugar for iterator and in resulting bytecode they will look the same way.

Related

Map.keySet() read sequence?

I have Map<String, List<String>> map now, putting two values inside Map, now when read keyset from map gives in different sequence in different device.
private Map<String, List<String>> map = new HashMap<>();
map.put("First", new ArrayList<String>());
map.put("Second", new ArrayList<String>());
Now, Read keys from this map.
Set<String> keys = map.keySet();
for (int i = 0; i < map.size(); i++) {
Log.d("key", keys.toArray()[i].toString());
}
OUTPUT IN OREO 8.0
D/Key : First
D/Key : Second
OUTPUT in BELOW 8.0
D/Key : Second
D/Key : First
I got a solution until we defined Set as SortedSet ,we getting key sequence in different order.
SortedSet<String> keys = new TreeSet<>(map.keySet());
for (int i = 0; i < map.size(); i++) {
Log.d("key", keys.toArray()[i].toString());
}
You're using the HashMap as the data structure. As in HashMap, the order of insertion is not maintained thus you're getting a random order of the keys. If you want to maintain the order of insertion, simply use a LinkedHashMap. The order in which you put the data is maintained and simply you can iterate over it.
Sample code for LinkedHashMap:
Map<String, String> map = new LinkedHashMap<>();
map.put("key1", "value2");
map.put("key3", "value4");
map.put("key5", "value6");
map.put("key7", "value8");
Set<String> keySet = map.keySet();
for(String st: keySet){
System.out.println(st);
}
for(Map.Entry<String, String> entry : map.entrySet()){
System.out.println(entry.getKey() + " " + entry.getValue());
}
Output:
key1
key3
key5
key7
key1 value2
key3 value4
key5 value6
key7 value8
It has nothing to do with the android OS. The resulting Set of HashMap has no order. However there are Sets with an order e.g. TreeSet.

Java - HashMap Iteration - Exception

I want to iterate a HashMap like:
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
map.replace(entry.getKey(), entry.getValue()-1);
if (entry.getValue() == 0) {
map.remove(entry.getKey(), 0);
}
}
This ends in an Exception: java.util.ConcurrentModificationException
Any solutions?
Kind regards
Iterator<Map.Entry<Integer, Integer>> entryItr = map.entrySet().iterator();
while (entryItr.hasNext()) {
Map.Entry<Integer, Integer> entry = entryItr.next();
if (entry.getValue() > 1) {
entry.setValue(entry.getValue() - 1);
} else {
entryItr.remove();
}
}
You're removing items from the map as you're iterating through it. This is what's causing the exception.
To get a bit of intuition as to why this is: if your map contains three items and on the first iteration you remove the first item, should the next item be the second, or third? i.e. should the iteration continue as though the removed item was still there? And if so, how?
You can get around this by using an iterator on the map which safely goes through each element of the map.
You can't remove elements from an existing Set without using Iterator, otherwise, it will throw ConcurrentModificationException
So, place values to a new Map object if(value-1 !=0) as shown below:
Map<Integer, Integer> map = new HashMap<>();
Map<Integer, Integer> newMap = new HashMap<>();
Iterator<Integer> iterator =map.keySet().iterator();
while(iterator.hasNext()) {
int key = iterator.next();
int value = map.get(key);
if(value-1 !=0) {
newMap.put(key, value-1);
}
}

How to replace ALL keys in java map? [duplicate]

This question already has answers here:
Changing HashMap keys during iteration
(5 answers)
Closed 6 years ago.
I want to replace keys in my map.
I have the following code:
Map<String, Object> map = new HashMap<String, Object>();
map.put("a", "1");
map.put("b", "2");
map.put("c", "3");
map.put("d", "4");
map.put("e", "5");
Iterator<Map.Entry<String, Object>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Object> next = iterator.next();
Object o = next.getValue();
//how to add new element ?
//...
iterator.remove();
}
I want to achieve map with keys
a1->1
b2->2
c3->3
d4->4
e5->5
If I use in loop map.put(next.getKey() + next.getValue(), next.getValue()); it will lead to ConcurrentModificationException.
To avoid a ConcurrentModificationException, you need to add the new key/value pairs to a separate map, and then use putAll to add that map into the original one.
Map<String, Object> newMap = new HashMap<>();
while (iterator.hasNext()) {
Map.Entry<String, Object> entry = iterator.next();
iterator.remove();
newMap.put(...); // Whatever logic to compose new key/value pair.
}
map.putAll(newMap);

Get Key value from iterator

I have a HashMap, which contains another HashMap. I want to iterate over the first HashMap and use the Key values from that. Then, as I iterate over the first HashMap I want to start an inner loop iterating over the second HashMap, getting all the values.
The problem I have so far is that I can't figure out how to get the keys from the Iterator.
HashMap<String, HashMap<Integer, String>> subitems = myHashMap.get("mainitem1");
Collection c = subitems.values();
Iterator itr = c.iterator();
while(itr.hasNext())
{
// Get key somehow? itr.getKey() ???
// contains the sub items
HashMap productitem = (HashMap)itr.next();
}
The data that i get from subitems is this:
{Item1{0=sub1, 1=sub2}, Item2{0=sub3, 1=sub4}}
Then, in the while loop productitem contains the 'sub items'. But i can't find out where i can get the key value 'Item1' and 'Item2' from.
How can i get those?
You can't get the key from values().iterator().
You need to use entrySet().iterator(). That will return Map.Entry<K,V> objects on which you can call getKey() and getValue().
for (Map.Entry<Integer,Key> entry : subitems.keySet()) {
Integer key = entry.getKey();
String value = entry.getValue();
// do stuff
}
I'd also like to add that having deeply nested maps of lists of maps is usually a sign that you really want to write custom classes to hold your data. Especially when the maps have pre-defined keys to be used and interpretation of the values in the lists depends on the position within the list! I call this code smell "object denial".
You can't go from value to key in a map. (There may be several keys mapping to the same value!)
You can iterate over the map entries though using subitems.entrySet().iterator(), or you can iterate over the keys, and in each iteration retrieve the associated value through subitems.get(key).
You could do something like this (using iterators):
Set<Entry<String, HashMap<Integer, String>>> c = subitems.entrySet();
Iterator<Entry<String, HashMap<Integer, String>>> iterator = c.iterator();
while(iterator.hasNext())
{
Entry<String, HashMap<Integer, String>> entry = iterator.next();
System.out.println("key:" + entry.getKey());
HashMap<Integer, String> innerMap = entry.getValue();
if (innerMap == null) {
continue;
}
Iterator<Entry<Integer, String>> innerIterator = innerMap.entrySet().iterator();
while (innerIterator.hasNext()) {
Entry<Integer, String> innerEntry = innerIterator.next();
System.out.println("key:" + innerEntry.getKey() + " value: " + innerEntry.getValue());
}
}
or like this using foreach structure:
for (Entry<String, HashMap<Integer,String>> entry : subitems.entrySet())
{
System.out.println("key:" + entry.getKey());
HashMap<Integer, String> innerMap = entry.getValue();
if (innerMap == null) {
continue;
}
for (Entry<Integer, String> innerEntry : innerMap.entrySet())
System.out.println("key:" + innerEntry.getKey() + " value: " + innerEntry.getValue());
}
}
java Collections provide facility of EntrySet. This is a list of objects which contain individual keys and values as its properties. You can take a iterator out of this list.
You can get keys as follows.
Iterator i= subitems.entrySet().iterator();
while(i.hasNext()){
String key= i.next().getkey();
}
You can iterate over entries using entrySet().iterator() on the first HashMap or get the keys and iterate over them: Instead of subitems.values().iterator() use subitems.keys().iterator() and use the next key to get the inner hashmap.

remove key from hash table

I want to remove key from hash Table without using the remove function. so give me some idea.
You can emulate removed keys by supplementing a Map<K,V> map with a Set<K> removedKeys.
To remove a key, just removedKeys.add(key);.
Whenever a K key is queried, you see if removedKeys.contains(key). If it does, then key has effectively been "removed" from map.
Note that this is a very peculiar way of doing things, and keeping the two structures in sync may cause later headaches. It's more acceptable if removedKeys is localized and short-lived, e.g. when you're iterating over the entries of a Map using for-each and want to remove some keys later, while avoiding ConcurrentModificationException.
So you may have something like this:
static void removeEvenKeys(Map<Integer,String> map) {
Set<Integer> removedKeys = new HashSet<Integer>();
for (Map.Entry<Integer,String> entry : map.entrySet()) {
if (entry.getKey() %2 == 0) {
removedKeys.add(entry.getKey());
}
}
map.keySet().removeAll(removedKeys);
}
And then elsewhere:
Map<Integer,String> map = new HashMap<Integer,String>();
map.put(1, "One");
map.put(2, "Two");
map.put(3, "Three");
map.put(4, "Four");
removeEvenKeys(map);
System.out.println(map);
// "{1=One, 3=Three}"
See also
Effective Java 2nd Edition, Item 52: Refer to objects by their interfaces
Related questions
Java hashmap vs hashtable
Java: Efficient Equivalent to Removing while Iterating a Collection
You can call remove() on an Iterator instead of on the Hashtable itself:
Hashtable<String, String> map = new Hashtable<String, String>();
map.put("one", "een");
map.put("two", "twee");
map.put("three", "drie");
for (Iterator<Map.Entry<String, String>> i = map.entrySet().iterator(); i.hasNext(); ) {
Map.Entry<String, String> entry = i.next();
if ("two".equals(entry.getKey())) {
// Removes entry from Hashtable; note, this is not the Hashtable.remove() method
// but the Iterator.remove() method
i.remove();
}
}
System.out.println(map);
(NOTE: You should use HashMap instead of the legacy collection class Hashtable).

Categories

Resources