I have the following Java code:
public void myMethod (final Map pFeatureGroupsFromPackage) {
final Set<String> keys = pFeatureGroupsFromPackage.keySet();
for (final String key : keys) {
tmpList = (List<FeatureKey>) pFeatureGroupsFromPackage.get(key);
// do whatever
}
}
I am getting a warning from "findBugs" telling the following:
Method myMethod makes inefficient use of keySet iterator instead of entrySet iterator.
The warning is done at the tmpListassignment.
I do not understand why this is inefficient. In fact the keyslist is computed only once.
Any comment? Thanks.
Instead of iterating over the keySet and calling get to get the corresponding value for each key, iterate over the entrySet:
final Set<Map.Entry<String, List<FeatureKey>>> entries = pFeatureGroupsFromPackage.entrySet();
for (Map.Entry<String, List<FeatureKey>> entry : entries) {
String key = entry.getKey();
List<FeatureKey> tmpList = entry.getValue();
// do whatever
}
That way you don't have to do a lookup in the map for every key; you directly get the key and value in one go.
Also, declare your Map with type parameters:
public void myMethod (final Map<String, List<FeatureKey>> pFeatureGroupsFromPackage) {
// ...
}
you're getting all the keys and then you search for every key in the collection
a Map.EntrySet iteration would be much faster, a small example:
But you also should use generics...
Set entries = map.entrySet();
Iterator entryIter = entries.iterator();
System.out.println("The map contains the following associations:");
while (entryIter.hasNext()) {
Map.Entry entry = (Map.Entry)entryIter.next();
Object key = entry.getKey(); // Get the key from the entry.
Object value = entry.getValue(); // Get the value.
System.out.println( " (" + key + "," + value + ")" );
}
This could help you:
Map map = new HashMap();
Iterator entries = map.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry entry = (Map.Entry) entries.next();
Integer key = (Integer)entry.getKey();
Integer value = (Integer)entry.getValue();
System.out.println("Key = " + key + ", Value = " + value);
}
Sample code:
for (Map.Entry < Integer, List < FeatureKey >>> i: map.entrySet()) {
System.out.println(i.getValue() + " " + i.getKey()));
}
It could be that you are querying the map twice:
first for the keys,
and second for the values
Using entryset iterator will iterate over the map once.
Accessing the HashMap via keySet iterator is even faster than using the keySet iterator on the TreeMap.
Hey Luixv,
The reason using keysey iterator is less effective than entryset iteratot is that with the first option you still have to use the Map.get(key) lookeup which is avoided with the second option.
Related
Is there a way to start iteration in HashMap from a particular key?
Suppose my map is :
Map map = new HashMap();
map.put(1,"A");
map.put(2,"B");
map.put(3,"B");
map.put(4,"B");
map.put(5,"F");
map.put(6,"Z");
And I want the iteration to start from key 2.
The regular iteration involves :
public static void printMap(Map map) {
Iterator it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry)it.next();
System.out.println(pair.getKey() + " = " + pair.getValue());
}
}
But how to start the iteration from a particular key?
Your question is based on a misunderstanding of what a HashMap is. In particular, if you started at the key 2 and iterated the remaining entries, there is no guarantee that you would get entries with keys 2, 3, 4, 5 and 6 ... in that order, or in any order.
The order of iteration for a HashMap is undefined, and in most cases unpredictable.
However ... if you used a LinkedHashMap or a TreeMap and iterated the entries then you would get them in a defined order:
a LinkedHashMap would (typically) give the entries in insertion order
a TreeMap would give the entries in comparison order of the keys.
If you use a LinkedHashMap, the way to get all entries starting from a given key (in insertion order) is to iterate from the start until you get to the key you want. For example:
public static void printMapFrom(LinkedHashMap<K, V> map, K from) {
boolean found = false;
for (Map<K, V>.Entry entry : map.entrySet()) {
if (!found && !from.equals(entry.getKey())) {
continue;
}
found = true;
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
If you use a TreeMap, the way to do it is to use tailMap(key) to get the submap of entries from the key to the end. Then you iterate the submap.
public static void printMapFrom(SortedMap<K, V> map, K from) {
for (Map<K, V>.Entry entry : map.tailMap(from).entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
If you actually don't care that the order of keys in a HashMap is indeterminate, then you can use the LinkedHashMap version above with a plain HashMap or a ConcurrentHashMap.
first define your map Map<Integer, String> map = new LinkedHashMap<Integer,String>();
And then you can use like it
for(Map.Entry<Integer, String> entry: map.entrySet()){
if(entry.getKey() == 1){
continue;
}
System.out.println(entry.getKey() +" : "+ entry.getValue());
}
This question already has answers here:
Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop
(31 answers)
Closed 5 years ago.
I was doing:
for (Object key : map.keySet())
if (something)
map.remove(key);
which threw a ConcurrentModificationException, so i changed it to:
for (Object key : new ArrayList<Object>(map.keySet()))
if (something)
map.remove(key);
this, and any other procedures that modify the map are in synchronized blocks.
is there a better solution?
Here is a code sample to use the iterator in a for loop to remove the entry.
Map<String, String> map = new HashMap<String, String>() {
{
put("test", "test123");
put("test2", "test456");
}
};
for(Iterator<Map.Entry<String, String>> it = map.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<String, String> entry = it.next();
if(entry.getKey().equals("test")) {
it.remove();
}
}
As of Java 8 you could do this as follows:
map.entrySet().removeIf(e -> <boolean expression>);
Oracle Docs: entrySet()
The set is backed by the map, so changes to the map are reflected in the set, and vice-versa
Use a real iterator.
Iterator<Object> it = map.keySet().iterator();
while (it.hasNext())
{
it.next();
if (something)
it.remove();
}
Actually, you might need to iterate over the entrySet() instead of the keySet() to make that work.
is there a better solution?
Well, there is, definitely, a better way to do so in a single statement, but that depends on the condition based on which elements are removed.
For eg: remove all those elements where value is test, then use below:
map.values().removeAll(Collections.singleton("test"));
UPDATE
It can be done in a single line using Lambda expression in Java 8.
map.entrySet().removeIf(e-> <boolean expression> );
I know this question is way too old, but there isn't any harm in updating the better way to do the things :)
ConcurrentHashMap
You can use java.util.concurrent.ConcurrentHashMap.
It implements ConcurrentMap (which extends the Map interface).
E.g.:
Map<Object, Content> map = new ConcurrentHashMap<Object, Content>();
for (Object key : map.keySet()) {
if (something) {
map.remove(key);
}
}
This approach leaves your code untouched. Only the map type differs.
Java 8 support a more declarative approach to iteration, in that we specify the result we want rather than how to compute it. Benefits of the new approach are that it can be more readable, less error prone.
public static void mapRemove() {
Map<Integer, String> map = new HashMap<Integer, String>() {
{
put(1, "one");
put(2, "two");
put(3, "three");
}
};
map.forEach( (key, value) -> {
System.out.println( "Key: " + key + "\t" + " Value: " + value );
});
map.keySet().removeIf(e->(e>2)); // <-- remove here
System.out.println("After removing element");
map.forEach( (key, value) -> {
System.out.println( "Key: " + key + "\t" + " Value: " + value );
});
}
And result is as follows:
Key: 1 Value: one
Key: 2 Value: two
Key: 3 Value: three
After removing element
Key: 1 Value: one
Key: 2 Value: two
You have to use Iterator to safely remove element while traversing a map.
I agree with Paul Tomblin. I usually use the keyset's iterator, and then base my condition off the value for that key:
Iterator<Integer> it = map.keySet().iterator();
while(it.hasNext()) {
Integer key = it.next();
Object val = map.get(key);
if (val.shouldBeRemoved()) {
it.remove();
}
}
An alternative, more verbose way
List<SomeObject> toRemove = new ArrayList<SomeObject>();
for (SomeObject key: map.keySet()) {
if (something) {
toRemove.add(key);
}
}
for (SomeObject key: toRemove) {
map.remove(key);
}
And this should work as well..
ConcurrentMap<Integer, String> running = ... create and populate map
Set<Entry<Integer, String>> set = running.entrySet();
for (Entry<Integer, String> entry : set)
{
if (entry.getKey()>600000)
{
set.remove(entry.getKey());
}
}
Maybe you can iterate over the map looking for the keys to remove and storing them in a separate collection. Then remove the collection of keys from the map. Modifying the map while iterating is usually frowned upon. This idea may be suspect if the map is very large.
Set s=map.entrySet();
Iterator iter = s.iterator();
while (iter.hasNext()) {
Map.Entry entry =(Map.Entry)iter.next();
if("value you need to remove".equals(entry.getKey())) {
map.remove();
}
}
Good day, this is kind of confusing me now(brain freeze!) and seem to be missing something. Have an ArrayList which i populate with a HashMap. now i put in my HashMap and arraylist.
Map.put(DATE, value1);
Map.put(VALUE, value2);
arraylist.put(Map);
Since am parsing a JSON, the arraylist increases in significant size. now my question is how do you get the values from both map keys in the arraylist? i have tried this
if(!list.isEmpty()){ // list is an ArrayList
for(int k = 0; k < list.size(); k++){
map = (HashMap)list.get(k);
}
}
Log.d(TAG, "map size is" + map.size());
String [] keys = new String[map.size()];
String [] date_value = new String[map.size()];
String [] value_values = new String[map.size()];
int i = 0;
Set entries = map.entrySet();
Iterator iterator = entries.iterator();
while(iterator.hasNext()){
Map.Entry mapping = (Map.Entry)iterator.next();
keys[i] = mapping.getKey().toString();
date_value[i] = map.get(keys[i]);
if(keys[i].equals(DATE)){
date_value[i] = map.get(keys[i]);
} else if(keys[i].equals(VALUE)){
value_values[i] = map.get(keys[i]);
}
i++;
}
But i can't seem to get all the values. the Map size always return a value of 2, which is just the elements. how can i get all the values from the Map keys in the ArrayList? Thanks
Why do you want to re-invent the wheel, when you already have something to do your work. Map.keySet() method gives you a Set of all the keys in the Map.
Map<String, Integer> map = new HashMap<String, Integer>();
for (String key: map.keySet()) {
System.out.println("key : " + key);
System.out.println("value : " + map.get(key));
}
Also, your 1st for-loop looks odd to me: -
for(int k = 0; k < list.size(); k++){
map = (HashMap)list.get(k);
}
You are iterating over your list, and assigning each element to the same reference - map, which will overwrite all the previous values.. All you will be having is the last map in your list.
EDIT: -
You can also use entrySet if you want both key and value for your map. That would be better bet for you: -
Map<String, Integer> map = new HashMap<String, Integer>();
for(Entry<String, Integer> entry: map.entrySet()) {
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
P.S.: -
Your code looks jumbled to me. I would suggest, keep that code aside, and think about your design one more time. For now, as the code stands, it is very difficult to understand what its trying to do.
List constructor accepts any data structure that implements Collection interface to be used to build a list.
To get all the keys from a hash map to a list:
Map<String, Integer> map = new HashMap<String, Integer>();
List<String> keys = new ArrayList<>(map.keySet());
To get all the values from a hash map to a list:
Map<String, Integer> map = new HashMap<String, Integer>();
List<Integer> values = new ArrayList<>(map.values());
Try it this way...
I am considering the HashMap with key and value of type String, HashMap<String,String>
HashMap<String,String> hmap = new HashMap<String,String>();
hmap.put("key1","Val1");
hmap.put("key2","Val2");
ArrayList<String> arList = new ArrayList<String>();
for(Map.Entry<String,String> map : hmap.entrySet()){
arList.add(map.getValue());
}
Create an ArrayList of String type to hold the values of the map. In its constructor call the method values() of the Map class.
Map <String, Object> map;
List<Object> list = new ArrayList<Object>(map.values());
Put i++ somewhere at the end of your loop.
In the above code, the 0 position of the array is overwritten because i is not incremented in each loop.
FYI: the below is doing a redundant search:
if(keys[i].equals(DATE)){
date_value[i] = map.get(keys[i]);
} else if(keys[i].equals(VALUE)){
value_values[i] = map.get(keys[i]);
}
replace with
if(keys[i].equals(DATE)){
date_value[i] = mapping.getValue();
} else if(keys[i].equals(VALUE)){
value_values[i] = mapping.getValue()
}
Another issue is that you are using i for date_value and value_values. This is not valid unless you intend to have null values in your array.
This is incredibly old, but I stumbled across it trying to find an answer to a different question.
my question is how do you get the values from both map keys in the arraylist?
for (String key : map.keyset()) {
list.add(key + "|" + map.get(key));
}
the Map size always return a value of 2, which is just the elements
I think you may be confused by the functionality of HashMap. HashMap only allows 1 to 1 relationships in the map.
For example if you have:
String TAG_FOO = "FOO";
String TAG_BAR = "BAR";
and attempt to do something like this:
ArrayList<String> bars = ArrayList<>("bar","Bar","bAr","baR");
HashMap<String,String> map = new HashMap<>();
for (String bar : bars) {
map.put(TAG_BAR, bar);
}
This code will end up setting the key entry "BAR" to be associated with the final item in the list bars.
In your example you seem to be confused that there are only two items, yet you only have two keys recorded which leads me to believe that you've simply overwritten the each key's field multiple times.
Suppose I have Hashmap with key datatype as KeyDataType
and value datatype as ValueDataType
HashMap<KeyDataType,ValueDataType> list;
Add all items you needed to it.
Now you can retrive all hashmap keys to a list by.
KeyDataType[] mKeys;
mKeys=list.keySet().toArray(new KeyDataType[list.size()]);
So, now you got your all keys in an array mkeys[]
you can now retrieve any value by calling
list.get(mkeys[position]);
Java 8 solution for produce string like "key1: value1,key2: value2"
private static String hashMapToString(HashMap<String, String> hashMap) {
return hashMap.keySet().stream()
.map((key) -> key + ": " + hashMap.get(key))
.collect(Collectors.joining(","));
}
and produce a list simple collect as list
private static List<String> hashMapToList(HashMap<String, String> hashMap) {
return hashMap.keySet().stream()
.map((key) -> key + ": " + hashMap.get(key))
.collect(Collectors.toList());
}
It has method to find all values from map:
Map<K, V> map=getMapObjectFromXyz();
Collection<V> vs= map.values();
Iterate over vs to do some operation
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.
In Python, you can have key,value pairs in a dictionary where you can loop through them, as shown below:
for k,v in d.iteritems():
print k,v
Is there a way to do this with Java HashMaps?
Yes - for example:
Map<String, String> map = new HashMap<String, String>();
// add entries to the map here
for (Map.Entry<String, String> entry : map.entrySet()) {
String k = entry.getKey();
String v = entry.getValue();
System.out.printf("%s %s\n", k, v);
}
The HashMap.entrySet() will return beans of key value pairs similar to the dictionary.iteritems(). You can then loop through them.
I think is the closest thing to the Python version.
As shown in the answers, there are basically two ways to iterate over a Map (let's assume Map<String, String> in those examples).
Iterate over Map#entrySet():
for (Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
Iterate over Map#keySet() and then use Map#get() to get the value for every key:
for (String key : map.keySet()) {
System.out.println(key + "=" + map.get(key));
}
The second one is maybe more readable, but it has a performance cost of unnecessarily calling get() on every iteration. One may argument that creating the keyset iterator is less expensive because it doesn't need to take values into account. But believe it or not, the keySet().iterator() creates and uses the same iterator as entrySet().iterator(). The only difference is that in case of the keySet() the next() call of the iterator returns it.next().getKey() instead of it.next().
The AbstractMap#keySet()'s javadoc proves this:
The subclass's iterator method returns a "wrapper object" over this map's entrySet() iterator.
The AbstractMap source code also proves this. Here's an extract of keySet() method (somewhere around line 300 in Java 1.6):
public Iterator<K> iterator() {
return new Iterator<K>() {
private Iterator<Entry<K,V>> i = entrySet().iterator(); // <-----
public boolean hasNext() {
return i.hasNext();
}
public K next() {
return i.next().getKey(); // <-----
}
public void remove() {
i.remove();
}
};
}
Note that readability should be preferred over premature optimization, but it's important to have this in mind.
Set<Map.Entry> set = d.entrySet();
for(Map.Entry i : set){
System.out.println(i.getKey().toString() + i.getValue().toString);
}
Something like that...
In Java, you can do the same like the following.
HashMap<String, String> h = new HashMap<String, String>();
h.put("1","one");
h.put("2","two");
h.put("3","three");
for(String key:h.keySet()){
System.out.println("Key: "+ key + " Value: " + h.get(key));
}