I've got a function filling a HashMap(rMap) of String arrays. Once certain conditions are met e.g r.Map.size() != 0 I then, in another file (rMap is a Global variable) call the following String array[] = rMap.get(0) from this I attempt to System.out.println(array[0]) .
Thats the run of the program and I get a null pointer at System.out.println(array[0]);. Anyone have any ideas why this happens?
EDIT: I'm filling the map like so..
String center[] = new String[] { tname, tmessage, tlink, tsname };
Global.rMap.put(index, center);
Where all values in the array are variables that are strings. So the value I'm accessing it tname and It's not equal to null. I've checked. My Key value is a String
The array reference is null, most likely because no value (or a null) has been added to rMap, with key 0.
If possible, use generics to ensure that your keys are the correct type. You might also print out the values of the map prior to fetching array to see what is in the map. Stepping through the code with a debugger, with a watch on the rMap will also show what the map contains and when it is changed.
How are you filling the map? Are you certain that you're putting an non-null entry with an Integer key of 0 into it?
Well, we can be pretty certain that you aren't. Possible reasons:
An error in the filling code that results in the intended put not being executed, or with a different key value
You're using Short or Byte objects as keys
You're putting a null value into the map under the 0 key
You can answer this question for yourself by running the code in a debugger and looking at the contents of the map.
Update:
My Key value is a String
Well, that's your problem right there. rMap.get(0) will look for an Integer, and it will not match the entry for a String "0".
HashMap allows null values, so the value you are getting with String array[] =rMap.get(0); may be null. Accessing the null array then throws the NPE.
Try rMap.get(Integer.valueOf(0));
It's an issue when you invoke the get method of Map implementation, the signature of get method of java.util.Map is get(java.lang.Object),thus,any object will be accepted as its argument.
The key that works fine is either pass a string(value=0) as a key or overrides the hashCode and equals methods of argument object that is not a java.lang.String object.
The get() method of Hashmap takes a key, not an index, to identify the value you want to get. If you want an ordered list of items, you'll need to use a List subclass (or enforce the ordering, yaourself). If you want to use a Hashmap, use the keys() method to get an enumeration of all the map's keys.
(removed above text, due to question clarification. leaving below text as, even though it's not the problem, it is an important consideration)
Also, you'll need to be very careful not to create race conditions, since you're working across threads. While Java's native Hashtable is synchronized, that doesn't mean the data in it is. That is, you can MyObj obj = get(xxx) in one htread, Nd start manipulating the obj in two separate threads, possibly stepping on each other. Depending upon your application, you may want to use Hashtable.remove() so that the data is gone from the map and cannot be re-used, or you may need some synchronized blocks (remove() may well be the simpler implementation, thoguh you'd have to gracefully handle conditions where the map first has data, then that data is gone).
Related
Today I was fixing one defect and found a very interesting thing.
I was trying to put a key value pair in hashmap. (I was assuming that key is there but later it was found to be null).
So while retrieving the value using a key , I was not getting null every time.
Later I found that key is null , I corrected it.
But then I see the code for put method of Hashmap.
Why does it does not gives an exception when the key is null ?
It calls putForNullKey private method. What does it do?
But i am thinking it should give some exception if the key is null.
Why they have not implemented it like that?
Key Value pair is not useful if a key is null?
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/HashMap.java#HashMap.putForNullKey%28java.lang.Object%29
From the Javadoc for HashMap:
Hash table based implementation of the Map interface.
This implementation provides all of the optional map
operations, and permits null values and the null key
This is by design, and it is documented. The 'why' question is hard to answer, but it has been that way since HashMap (and before that, Hashtable) were introduced (Edit, actually, Hashtable did not allow nulls).
As to why it has the putForNullKey, well HashMap relies on the hashCode() of a key to place it, and, since it can't get the hashCode() from a null value, it has to do it as a special case.
HashMap allows only one null key. So whenever any one want to put some value with null it calls putForNullKey method inside the put method and in putForNullKey method it places the value at zero index.
For getting value by null key it also has a method getForNullKey which it calls from inside the get method.
It's one of the differences between a Hashtable and a HashMap.
Hashtable does not allow null keys or values. HashMap allows one null key and any number of null values.
Usually, we use the null key to represent the default case (i.e. the value that should be used if a given key isn't present)
I have string array str[10][3], it is full of values.
Now I want to make it empty ie. delete all the values of str.
I have defined str as static, also I want empty this string from another claas in same package.
Can I use null here.
Plz suggest some way. thanks
Sure, you can use null but first wonder if you really need to nullify them, because null values will mostly generate problems and require special handling. You could use the empty string "" to avoid having problems with NullPointerExceptions.
Just reassign a new array to the same variable will do the trick, Java will take care about collecting garbaged data:
ClassName.str = new String[10][3];
str = new String[10][3]; will assign an empty 2D array to str.
One can always sets a value to null as long as it is no primitive type (int, char, boolean, ...) or a readonly value. I assume it's neither of them so the answer is YES.
So a solution would be:
str = null;
If you want to fill up your structure with new values you could use
str = new String[10][3];
however I don't see why you should do that, It's not because you don't need the data you should get rid of it. Furthermore in the new str there is also data (the initial null-strings). But if you wan't to store new data into the structure, there is no problem to do so. This paradigm is sometimes called "lazy". It means: "don't do anything unless you absolutly have to"
By setting null the data will not disappear at once. It is sheduled to be removed by the garbage collector. A program that only runs at some low frequency or if the program is in need of memory. In that case it wil mark the memory as free so it can be reused.
Why does java.util.Map.values() allow you to delete entries from the returned Collection when it makes no sense to remove a key value pair based on the value? The code which does this would have no idea what key the value(and hence a key) being removed is mapped from. Especially when there are duplicate values, calling remove on that Collection would result in an unexpected key being removed.
it makes no sense to remove a key value pair based on the value
I don't think you're being imaginative enough. I'll admit there probably isn't wide use for it, but there will be valid cases where it would be useful.
As a sample use case, say you had a Map<Person, TelephoneNumber> called contactList. Now you want to filter your contact list by those that are local.
To accomplish this, you could make a copy of the map, localContacts = new HashMap<>(contactList) and remove all mappings where the TelephoneNumber starts with an area code other than your local area code. This would be a valid time where you want to iterate through the values collection and remove some of the values:
Map<Person, TelephoneNumber> contactList = getContactList();
Map<Person, TelephoneNumber> localContacts = new HashMap<Person, TelephoneNumber>(contactList);
for ( Iterator<TelephoneNumber> valuesIt = localContacts.values().iterator(); valuesIt.hasNext(); ){
TelephoneNumber number = valuesIt.next();
if ( !number.getAreaCode().equals(myAreaCode) ) {
valuesIt.remove();
}
}
Especially when there are duplicate values, calling remove on that Collection would result in an unexpected key being removed.
What if you wanted to remove all mappings with that value?
It has to have a remove method because that's part of Collection. Given that, it has the choice of allowing you to remove values or throwing an UnsupportedOperationException. Since there are legitimate reasons that you might want to remove values, why not choose to allow this operation?
Maybe there's a given value where you want to remove every instance
of it from the Map.
Maybe you want to trim out every third
key/value pair for some reason.
Maybe you have a map from hotel
room number to occupancy count and you want to remove everything from
the map where the occupancy count is greater than one in order to
find a room for someone to stay in.
...if you think about it more
closely, there are plenty more examples like this...
In short: there are plenty of situations where this might be useful and implementing it doesn't harm anyone who doesn't use it, so why not?
I think there is quite often a use for removing a value based on a key; other answers show examples. Given that, if you want to remove a certain value, why would you only want one particular key of it removed? Even if you did, you'd have to know which key you wanted to remove (or not, as the case may be), and then you should just remove it by key anyway.
The Collection returned is a special Collection, and its semantics are such that it knows how values in it relate back to the Map it came from. The javadoc indicates what Collection operation the returned collection supports.
Hashtable does not allow null keys or values, while HashMap allows null values and 1 null key.
Questions:
Why is this so?
How is it useful to have such a key and values in HashMap?
1. Why is this so?
HashMap is newer than Hashtable and fixes some of its limitations.
I can only guess what the designers were thinking, but here are my guesses:
Hashtable calculates a hash for each key by calling hashCode on each key. This would fail if the key were null, so this could be a reason for disallowing nulls as keys.
The method Hashtable.get returns null if the key is not present. If null were a valid value it would be ambiguous as to whether null meant that the key was present but had value null, or if the key was absent. Ambiguity is bad, so this could be a reason for disallowing nulls as values.
However it turns out that sometimes you do actually want to store nulls so the restrictions were removed in HashMap. The following warning was also included in the documentation for HashMap.get:
A return value of null does not necessarily indicate that the map contains no mapping for the key; it is also possible that the map explicitly maps the key to null.
2. How is it useful to have such a key and values in HashMap?
It is useful to explicitly store null to distinguish between a key that you know exists but doesn't have an associated value and a key that doesn't exist. An example is a list of registered users and their birthdays. If you ask for a specific user's birthday you want to be able to distinguish between that user not existing and the user existing but they haven't entered their birthday.
I can't think of any (good) reason for wanting to store null as a key, and in general I'd advise against using null as a key, but presumably there is at least one person somewhere that needs that keys that can be null.
Well, I think Mark Byers answered perfectly, so just a simple example where null values and keys can be useful:
Imagine you have an expensive function that always returns the same result for the same input. A map is a simple way for caching its results. Maybe sometimes the function will return null, but you need to save it anyway, because the execution is expensive. So, null values must be stored. The same applies to null key if it's an accepted input for the function.
HashTable is very old class , from JDK 1.0.The classes which are in place from JDK 1.0 are called Legacy classes and by default they are synchronized.
To understand this, first of all you need to understand comments written on this class by author.
“This class implements a hashtable, which maps keys to values. Any non-null object can be used as a key or as a value. To successfully store and retrieve objects from a hashtable, the objects used as keys must implement the hashCode method and the equals method.”
HashTable class is implemented on hashing mechanism, means to store any key-value pair, its required hash code of key object. HashTable calculates a hash for each key by calling hashCode on each key. This would fail If key would be null, it will not be able to give hash for null key, it will throw NullPointerException and similar is the case for value, throwing null if the value is null.
But later on it was realised that null key and value has its own importance, then revised implementations of HashTable were introduced like HashMap which allow one null key and multiple null values.
For HashMap, it allows one null key and there is a null check for keys, if the key is null then that element will be stored in a zero location in Entry array.
We cannot have more than one Null key in HashMap because Keys are unique therefor only one Null key and many Null values are allowed.
USE - Null key we can use for some default value.
Modified and better implementation of HashTable was later introduced as ConcurrentHashMap.
In addition to what answered by Mark Bayers,,
Null is considered as data and it has to be stored as a value for further checking. In many cases null as value can be used to check if key entry is there but no value is assigned to it, so some action can be taken accordingly. This can be done by first checking if key is there, and then getting value.
There is one more case in which just put whatever data is coming(without any check). All the checks are applied to it after getting it.
Whereas null as a key, i think can be used to define some default data. Usually null as a key does not make much sense.
Sir HashMap is also internally uses hashCode() method for inserting an element in HashMap, so I think this will be not the proper reason for "why HashTable allow null key"
It will make the Map interface easier to use / less verbose. null is a legitimate value for reference types. Making the map able to handle null keys and values will eliminate the need for null checking before calling the api. So the map api create less "surprises" during runtime.
For example, it is common that map will be used to categorize a collection of homogeneous objects based a single field. When map is compatible with null, the code will be more concise as it is just a simple loop without any if statement (of course you will need to make sure the collection does not have null elements). Fewer lines of code with no branch / exception handling will be more likely to be logically correct.
On the other hand, not allowing null will not make the map interface better/safer/easier to use. It is not practical to rely on the map to reject nulls - that means exception will be thrown and you have to catch and handle it. Or, to get rid of the exception you will have to ensure nothing is null before calling the map methods - in which case you don't care if map accepts null since you filtered the input anyway.
I have a function which returns an int value for a given key (from a HashMap<String, Integer>). If the key doesn't exist, I want to return something the caller can check for. It seems that, most commonly, this would be a "returns -1 if key doesn't exist" kind of thing. However, I can't reserve -1 for that purpose in my case, because negative numbers are feasible values for keys which do exist.
The only other options I have been able to come up with are the following:
Change return type to Integer wrapper class and check for null
Return something very unlikely, such as Integer.MIN_VALUE
Make an additional boolean keyExists(String key) function which should always be called first
Switch to float and use NaN instead
I am writing this in Java, but people from similar language backgrounds are welcome to post. Thanks!
The first option is, in my opinion, the cleanest. Magic numbers like -1 and Integer.MIN_VALUE are kind of messy, especially when the values aren't intuitive. That is an idiomatic C solution, which Java developers will hate you for. Depending on what you're actually using this for you could also throw a "KeyNotFoundException" if this only happens in "exceptional" circumstances.
I vote for throwing a checked exception here. Generally I dislike checked exceptions but it seems like a reasonable thing to do in this case. The case where the value is not present will need to be handled separately from the case where the value is present, using an exception would make that clear.
Actually your idea to add a keyExists method is the best of the ideas you list, because it doesn't rely on the user knowing to look for a special value. If you go that way then you could throw an exception as a backup plan in case the map contents change between the call to keyExists and the retrieval.
Although it depends heavily on the application and know constraints, I would prefer #1 above. The reason is because then it is explicit - it is always better to have an explicit situation than an implicit - such as MIN_VALUE - in my experience.
Another option is to have a wrapper object that contains the result value as a primitive int, but also has a status value or something similar. So it could be something like:
public class Wrapper {
private int value = Integer.MIN_VALUE;
private boolean isValid;
// appropriate getters and setters etc.
}
You could also include an enum instead of a boolean to have a state instead, depending on the complexity of the problem. If you see this element holding composite information - sets of information keyed of single keys, or something similar - a container object or status object can be very valuable in those cases.
float is unsafe as not all int values can be accurate represented as int values. long is a better options as all int values can be safely stored as long and you will have plenty more values for not-found.
If you are using a Map you have an Integer object anyway so why not return that (or null)
If you really want to use primitives (for efficiency ??) I suggest you look at TObjectIntHashMap instead. This uses primitive int values. To check for absense, you have to check containsKey() seperately.
Two situations are typical:
You have a high expectation of
finding a value for a particular
key.
You are not sure if a particular key
has a value stored.
If assumption 1 is wrong, then it's likely to indicate a bug, so protect your assumption in the access method with an assertion.
If 2 applies, how would you be sure about what's returned? so provide a test method such as "keyExists" and know absolutely before accessing the map.
In case 1, no checking is required, which is much cleaner, but the access will fail if you are wrong.
With special cases such as -1 or Integer.MIN_VALUE it is very hard to be sure that they won't be used.
Languages like Haskell, Scala and C# have special types to convey presence / absence of a value which is far better than use of null (if you forget to test you will likely get a NullPointerException)
Option 5: Throw an Exception
Although, in this case, I'd vote for using the Integer class.
I think you should combine options #1 and #3, since that's consistent with the behavior of the underlying HashMap. From HashMap's get method documentation:
Returns the value to which the specified key is mapped in this identity hash map, or null if the map contains no mapping for this key. A return value of null does not necessarily indicate that the map contains no mapping for the key; it is also possible that the map explicitly maps the key to null. The containsKey method may be used to distinguish these two cases.
Change return type to Integer wrapper class and check for null.
This is the more common option.