Hashmap get returns null - java

I have two Hashmaps
HashMap<Integer, Integer> inventoryRequirements = new HashMap<Integer, Integer>();
HashMap<Integer, Integer> inventory = new HashMap<Integer, Integer>();
I have a loop that checks current and adds to it:
for(Item item : items){
int currentRequirement = 0;
currentRequirement = inventoryRequirements.get(item.get_id());
inventoryRequirements.put(item.get_id(), currentRequirement++);
}
I have another loop that checks inventory and adds to it:
for(Item item : items){
int currentInventory = 0;
// this next line returns null
currentInventory = inventory.get(item.get_id());
inventory.put(item.get_id(), currentInventory++);
}
The first one works fine, but the second one pukes and returns a null. I don't understand why the second one does not work. Both are initially in the same state as depicted in the code sample.
EDIT
The two HM get populated as you see here - really! I know it may be hard to believe but the first one works and the second one does not.

Both of the loops you show will throw a NullPointerException (NPE) if the key you request via get() is not in the Map.
Map.get() returns null when the key is not present (or of course if the value stored with that key is null). An Integer (autoboxed type) that is null can not be autounboxed into an int so it throws an NPE.
The safe way of performing this is:
for (Item item : items) {
Integer currentRequirement = inventoryRequirements.get(item.get_id());
if (currentRequirement != null) {
inventoryRequirements.put(item.get_id(), currentRequirement++);
}
}
Of course, it's also completely possible that you have an Item in your collection that is null and that is what is throwing the NPE.

If the code you have provided is complete, then you haven't put anything in your hashmap.
So it will always return null.

You are getting a item from inventory but it's empty

The best practice is to write the code in the following manner:
for(Item item : items){
int currentRequirement = 0;
currentRequirement = inventoryRequirements.get(item.get_id());
if(currentRequirement!=null){
//update currentRequirement only if it exists in the map.
inventoryRequirements.put(item.get_id(), currentRequirement++);
} else {
//add it to the map otherwise.
inventoryRequirements.put(item.get_id(), 1);
}

Ugg. Also, when all else fails, don't overlook the possibility that it is not returning null because its not finding the key. It could be returning null because when the key/value pair was added... the value added was null. Just spent more time than I care to admit tracking this down.
So, to recap, there are at least two reasons the HashMap could be returning null:
It's not finding the key
It is finding the key, but the value inserted for the key is null
Doh!

Related

Iterate through List<Object> given from Value within a Map

I am relatively unexperienced using such Java code. For getting forward in my Selenium automation I want to iterate through a Map>.
Right now I try to get near that iteration with the following code:
static Map<String, List<WebElement>> map = new Map<String, List<WebElement>>;
for (Map.Entry<String, List<WebElement>> entry : map.entrySet()) {
for (int i = 0; i < entry.getValue().size(); i++) {
*need to find code*
}
}
My intention is to iterate through all the WebElements within the Value of one Key within map
Will "entry.getValue().size()" get the Size of the List in that case? And how may I get a certain item out of the list in such a case? Any better solutions maybe?
Best regards
You can access both the key and the value from each map entry and do whatever you need. The key in this case is a string, and its value is a List<WebElement>. Once you have the list in hand, you can access its size and iterate over it.
for (Map.Entry<String, List<WebElement>> entry : map.entrySet()) {
String key = entry.getKey();
List<WebElement> list = entry.getValue();
// to iterate over the list, you can try
for (int i=0; i < list.size(); ++i) {
WebElement we = list.get(i);
// do something with this web element
}
}
My intention is to iterate through all the WebElements within the Value of one Key within map
That should be easy enough:
for( WebElement element : map.get(key) ) {
//do whatever is appropriate
}
There's one problem with the above: if get(key) returns null (either the key is not mapped or the map contain's the value null for that key) you get a NullPointerException. To fix that could first get the map, check if you didn't get null, then iterate:
List<WebElement> list = map.get(key);
if( list != null ) {
for( WebElement element : list ) {
//do whatever is appropriate
}
}
You might also want to have a look at Guava's ListMultimap, which always will return a collection/list on get() and makes handling maps with list values a lot easier.
Will "entry.getValue().size()" get the Size of the List in that case?
Yes since entry.getValue() should return a List unless you mapped null for the given key. And since you get a List the call to size() will return the list's size.
And how may I get a certain item out of the list in such a case?
If you know the index of that element just check whether the list actually contains that index, i.e. whether index >= 0 && index < list.size(). Then just get it with list.get(index).
If you don't know the index you need to iterate over the list and inspect each element until you reach the end or found the element you need. Alternatively, if you can sort the list by the property you're checking, you could also use binary search to locate the element, if it exists.
Note, though, that LinkedList has linear cost for get(index) and thus isn't well suited for getting by index or binary search, at least not if the list contains many elements.

Data structure to count frequency of equal items

I need to have data structure like HashSet.
It should not add the same item into the collection
But instead of adding the same item, it should count times this item was added.
As I understand HashSet calculates hashCode at first, if hashCode is the same it checks equals method if true than it will not add an item, otherwise item with the same hashCode but another equals will be added to the bucket linked list.
What I need to do is just keep only unique objects like Set does, but using equals method only, and if objects are equal than increment counter associated with each object.
Is there any such data structure already implemented, or I should create my own ?
It seems that what you really need is a map. For every item you can have the number of items
public class ItemCounter<T>{
private Map<T, Integer> counts = new HashMap<T, Integer>();
public void addItem(T item){
Integer numberOfOcurrences = counts.get( item );
numberOfOcurrences = numberOfOcurrences == null ? 0 : numberOfOcurrences+1;
counts.put( item, numberOfOcurrences);
}
public Integer getCount( T item ){
Integer numberOfOcurrences = counts.get( item );
return numberOfOcurrences == null ? 0 : numberOfOcurrences;
}
}
The simplest way (without dependecies) is to have a HashMap<Element, Integer>. Or you can use Guava's MultiSet which has a count(Object) method to get the number of occurrences of an object in the collection.

how to handle null pointer in iteration with null key

In a recent interview, question I faced was
How can you handle null pointer when iterator encounters a null key
while iteration over a hashmap. assume my developer has inserted a
null key by mistake
My answer was: Just we need to check null!=entry.getKey().
he was not satisfied and said before that how will you handle.
How should I answer that question. When I was back.
I tried this
public class Main {
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>();
map.put(null, "null");
map.put("null",null);
map.put("test", "test");
Iterator<Entry<String, String>> it = map.entrySet().iterator();
while(it.hasNext()){
System.out.println(it.next().getKey());
}
}
}
output:
null
test
null
there is no exception. What was he trying to ask actually. or is that I am missing some concepts? Please guide me
map.remove(null)
From JavaDocs:
Returns the value to which this map previously associated the key, or null if the map contained no mapping for the key.
If this map permits null values, then a return value of null does not necessarily indicate that the map contained no mapping for the key; it's also possible that the map explicitly mapped the key to null.
The map will not contain a mapping for the specified key once the call returns.
Call it before iteration, and it will remove explicit null keys
I guess the key point that he want to test by this question is What happend when called the method next() on the object Iterator.
He maybe want to know whether or not you will programming like the following way when you want to iterate a map:
Map map = new HashMap();
Iterator iter = map.keySet().iterator();
while (iter.hasNext()) {
if (null != iter.next().key()) {
System.out.println(iter.next());
}
}
If you programming like above example, the next method will called twice, and you will not get the correct object that you really want to check. Instead, you should write code like this:
Map map = new HashMap();
Iterator iter = map.keySet().iterator();
while (iter.hasNext()) {
// Key point: define a refreence point to the object returned by the
// method `next()`
Entry entry = iter.next();
if (null != entry.key()) {
System.out.println(entry);
}
}

Array out of bound exception?

Consider the following code:
Map<Integer, Material> TestMap= new HashMap<Integer, Material>();
if (TestMap.get(index)!= null) {
index++;
}
What will happen if TestMap.get(index) is null? Some say it will exit the code, some say it will throw ArrayIndexOutOfBoundsException.
Your code won't throw an ArrayIndexOutOfBoundsException, for it's a HashMap. As per the documentation of the get() method of HashMap:
public V get(Object key)
Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key.
So if the HashMap does not contain a value for ìndex, if will return null, no problem there.
EDIT
If your HashMap was a List, and you added 10 elements, and you called get(25) on the List, then you'd get an ArrayIndexOutOfBoundsException.
So to summarize
if (TestMap.get(index)!= null) {
index++;
}
This piece of code doesn't throw any Exceptions (except when TestMap is null). If there's no value for the given key, get() returns null, and since you perform a null check, the if is not entered when the key doesnt exist in the map.

ArrayList in java, only doing an action once

For some reason, I'm drawing a blank on this one. I have an ArrayList that contains CDs (some of them identical in name) and I want to print a String that tells how many I have of each CD. For example, a string that says "You have: (1) AlbumOne, (2) AlbumTwo, (1) AlbumThree" etc. The CDs are not sorted. How can I do this?
One way to do it is to loop thru the array, and use a map that uses the objects as keys and the values as counts. So
Map<YourObject, Integer> counter ...
As you loop thru the array, do a get on the counter for the current object in the array. If you get null, initialize the value at that bucket in the map to be 1. If you have a value, increment it. Then you can loop over the map to get your readout.
Note that if you use a Hashmap, your objects have to implement the hashcode and equals method properly. You don't have to use your object, if it has keys or some other distinguishing field, the keys in your map can be that...
//aggregate details
Map<String, Integer> albumCounts = new HashMap<String, Integer>();
for (String album : albums) {
Integer count = albumCounts.get(album);
if (count == null) {
count = 0;
}
albumCounts.put(album, count + 1);
}
//print stats
System.out.println("You have:");
for (String album : albums) {
System.out.println("(" + albumCounts.get(album) + ") " + album);
}
Don't get confused about the Map. Use of Map is appropriate to solve such a problem (as you have posted) So please visit this link (tutorial) and read/learn about Map.

Categories