10 Replies Latest reply on Sep 20, 2010 1:36 PM by 843789

    HashMaps: NullPointerException when getting a value

    843789
      Hi, I'm a beginner in using Hashmap and there is something that is turning me crazy but should be very easy if I had the concepts clear.
      I'm trying to use a HashMap to store some float (energy) values for each point in space represented by a coordinate(x,y,z) defined in a simple class that I call Coord3d.
      I have apparently no problem in creating the hashmap and filling it up with the energy values for each coordinate.

      My problem comes when I try to read the value for any given coordinate:
      1.- If I use something like
                coord= new Coord3d((float) 0.0, (float) 0.0, (float) 0.0);
                energy= energyValues.get(coord);
      I get a NullPointer exception in the "get"

      2.- If I assign values directly as in:
                coord.x= (float) 0.0;
                coord.y= (float) 0.0;
                coord.z= (float) 0.0;
                energy= energyValues.get(coord);

      The "get" function of the Hasmap does not return the energy value of the searched coordinate but instead it returns the last stored value.

      Attached I send a very simple and short testcase that reproduces my problems.
      Thanks for any help and best regards,

      JBB
      import java.util.HashMap;
      public class testCaseHashMap {
           public static void main(String[] args) {
                HashMap<Coord3d, Float> energyValues;
                energyValues = new HashMap<Coord3d, Float>(); //Must use Object Float instead of primitive data type float 
                Coord3d coord= new Coord3d(-20.0f, -20.0f, -20.0f);
                float energy=0.0f;
                float x = 0,y = 0,z = 0;
                
                for(int incX=0; incX<2; incX++){
                     for(int incY=0; incY<2; incY++){
                          for(int incZ=0; incZ<2; incZ++){
                               x= (float) incX;
                               y= (float) incY;
                               z= (float) incZ;
                               energy= (float) x+y+z;
                               coord= new Coord3d(x, y, z);
                               energyValues.put(coord,energy);
                               System.out.println("x= "+String.valueOf(x)+" y= "+String.valueOf(y)+" z= "+String.valueOf(z)+" "+String.valueOf(energy));
                          }
                     }
                }     
       // If I use new I get a NullPointerException
                coord= new Coord3d((float) 0.0, (float) 0.0, (float) 0.0); 
      
      //If instead I set manually the values it doesn't produce an error but gets the last value instead of the one with matching key
                coord.x= (float) 0.0; 
                coord.y= (float) 0.0;
                coord.z= (float) 0.0;
      
                energy= energyValues.get(coord);
                System.out.println(String.valueOf(energy));
           }
      }
      And the simple definition of the Coord3d class:
      public class Coord3d {          
           /** Create a 3d coordinate.*/
           public Coord3d(float xi, float yi, float zi){
                x = xi;
                y = yi;
                z = zi;
           }
           
           public float x;
           public float y;
           public float z;
      }
        • 1. Re: HashMaps: NullPointerException when getting a value
          843789
          I haven't looked at all your code, but I do have to ask if the class that is being used for the HashMap key, Coord3d, has a hashCode and equals method override. Without these, the hashCode method in particular, there's no way to use these objects as keys since the HashMap uses the hashCode results to find the corresponding values held by the map.
          • 2. This Thread is now moved
            darrylburke
            Note: This thread was originally posted in the [Java Programming|http://forums.sun.com/forum.jspa?forumID=31] forum, but moved to this forum for closer topic alignment.
            • 3. Re: HashMaps: NullPointerException when getting a value
              796367
              JBBMovil, don't forget that HashMap.put() requires two Objects to be passed as arguments--not an Object and a Primitive. You may also want to override the Coord3d.equals() method to ensure that equality is based on the values of its coordinates. You definitely only need one FOR loop in your case, so you'll have to simplify your incremental logic.
              • 4. Re: HashMaps: NullPointerException when getting a value
                darrylburke
                HashMap.put() requires two Objects to be passed as arguments--not an Object and a Primitive.
                Autoboxing ;-)
                • 5. Re: HashMaps: NullPointerException when getting a value
                  796367
                  I figured there was some kind of javascript (interpreting) going on. I like the old java strict language way, you can trust it.
                  • 6. Re: HashMaps: NullPointerException when getting a value
                    EJP
                    I figured there was some kind of javascript (interpreting) going on.
                    There isn't. What is going on is compile-time autoboxing. No Javascript, no interpretation.
                    I like the old java strict language way, you can trust it.
                    It's still there.
                    • 7. Re: HashMaps: NullPointerException when getting a value
                      796367
                      Autoboxing. It probably solves the problem of having to rewrite old class files to include overloaded methods. If my assupmption is right, then I agree that it would help those who use java. Jeez, I did it again... that's a double cave-in-in-one.
                      • 8. Re: HashMaps: NullPointerException when getting a value
                        843789
                        OK, after some googling now I have learnt what autoboxing is (after using it... Object Float instead of primitive data type float ..., just in case some other novice reads this.)

                        So I get the NullPointerException because the get method returns a (Float)null and when it is cast into a float I get the exception because a float is a number and cannot be null, correct?.

                        And I get the null because I have not Overriden the equals() method in Coord3d.... and also the hashCode.

                        Is this hashCode really neccesary?
                        Where can I find an easy example of hashCode Override, because all the ones that I google seem too elaborate for my purposes.

                        Thanks everyone and best regards,

                        JBB
                        • 9. Re: HashMaps: NullPointerException when getting a value
                          796447
                          JBBMovil wrote:
                          Is this hashCode really neccesary?
                          Yes. Otherwise how is the hash table supposed to figure out where in the collection your new key might be? Without it, it would have to search each and every node's key and compare them with the desired key.
                          Where can I find an easy example of hashCode Override, because all the ones that I google seem too elaborate for my purposes.
                          Well, if you can't figure it out from all the available reading, frankly there's little hope you would understand it here either, donchathink?
                          • 10. Re: HashMaps: NullPointerException when getting a value
                            843789
                            Ok, thanks to everybody.
                            Yes, my problem was that I didn't have the equals() and hashCode() methods defined in Coord3d, the object that I used in the hashMap.

                            Simply defining them as follows and it works. Instead of using the complicated hashcode functions that I have found in the web I have defined a simple one for 3d coordinates.

                            I leave the code just in case it helps some other begginer.

                            Thanks,

                            JBB

                                 /**************************************************************/
                            
                                 @Override public boolean equals(Object aThat) {
                                      //check for self-comparison
                                      if ( this == aThat ) return true;
                            
                                      //use instanceof instead of getClass here for two reasons
                                      //1. if need be, it can match any supertype, and not just one class;
                                      //2. it renders an explict check for "that == null" redundant, since
                                      //it does the check for null already - "null instanceof [type]" always
                                      //returns false. (See Effective Java by Joshua Bloch.)
                                      if ( !(aThat instanceof Coord3d) ) return false;
                                      //Alternative to the above line :
                                      //if ( aThat == null || aThat.getClass() != this.getClass() ) return false;
                            
                                      //cast to native object is now safe
                                      Coord3d that = (Coord3d)aThat;
                            
                                      //now a proper field-by-field evaluation can be made
                                      return ((this.x==that.x) && (this.y==that.y) && (this.z==that.z));
                                 }     
                            
                                 @Override public int hashCode() {
                                      if ( fHashCode == 0 ) {
                                           fHashCode = (int)(this.x*100000000.0f+this.y*10000.0f+this.z);
                                      }
                                      return fHashCode;
                                 }
                                 /**************************************************************/
                                 private int fHashCode;