28

My code is similar to the following:

public class A {
        private HashMap<Character, Boolean> myMap;

        public A() {
            myMap = new HashMap<Character, Boolean>();
            String mychars = "asdfzxcvqwer";
            for (char c : mychars.toCharArray())
                myMap.put(c, true);
        }

        public void doo(String input) {
            StringBuilder output = new StringBuilder();
            for (char c : input.toCharArray()) {
                if (myMap.get(c))
                    output.append(c);
            }
        }
        //...
        //...
    }

Why am I getting a null pointer exception (NPE) at the line if (myMap.get(c))?

nabster
  • 1,561
  • 2
  • 20
  • 32
  • 1
    @talnicolas check his map declaration and also do is a reserved keyword in java, you cant use it as a method name – PermGenError Dec 03 '12 at 16:22
  • I typed out the code manually into SO -- apologies for both the errors. Thanks very much for the answers, everyone. I'll make the edits. –  Dec 03 '12 at 16:33

9 Answers9

65

If c is not contained in myMap, it will return null, which can't be unboxed as a boolean.

Try :

Boolean b = myMap.get(c);
if(b != null && b){
...
xlecoustillier
  • 16,183
  • 14
  • 60
  • 85
  • 4
    This is the correct answer. Also, `HashMap myMap` is a syntax error (should be `HashMap myMap`), and you can't name methods `do`. – durron597 Dec 03 '12 at 16:24
18

If myMap doesn't contain a key that matches c, then myMap.get(c) will return null. In that case, when the JVM unboxes what it expects to be a java.lang.Boolean object into a boolean primitive to execute the condition, it founds a null object and therefore throws a java.lang.NullPointerException.

The following block is equivalent to what you have in your example and should make it easier to understand why you would have a NullPointerException:

if (((Boolean) myMap.get(c)).booleanValue()) 

I would re-write your original condition as:

if ( myMap.containsKey(c) )

I hope this helps.

Nuno Guerreiro
  • 320
  • 1
  • 8
7

Change

if ( myMap.get(c) )

to

if ( myMap.containsKey(c) && myMap.get(c))
Jiji
  • 383
  • 1
  • 7
3

If there is no entity with required Character in map, then map.get(key) returns null and inside if statement it leads to NullPointerException throwing.

bellum
  • 3,642
  • 1
  • 17
  • 22
3

A stab in the dark: is there an entry in your map for the particular character assigned to c? If there isn't, Java may be trying to unbox a null value...

Dan Vinton
  • 26,401
  • 9
  • 37
  • 79
3

Changing this

for ( char c : input.toCharArray() )
{
  if ( myMap.get(c) )
     output.append(c);
}

For this

for ( char c : input.toCharArray() )
{
  if ( myMap.containsKey(c) )
     output.append(c);
}

Will make use of the map's defined method to check if a certain key is registered on the map. I'm leaving the for as it is, since you seem to want to check for a group of keys.

myMap.get(c) returns the value associated with that key, or null if the key is not registered.

As a side note, remember that if you use this method with custom objects you'll have to redefine the hashcode and equals methods.

Suggestion: I'm just suggesting this out of a remote idea I have, if it's not a correct interpretation of your code just ignore it. If your map only contains a boolean value to determine if certain value "is contained" or not, I strongly suggest you use a HashSet instead because a map is not doing any sense in that context.

Fritz
  • 9,987
  • 4
  • 30
  • 49
  • Good answer, +1. Do you happen to know if `containsKey(c)` is faster than `get(c) != null`? – durron597 Dec 03 '12 at 16:40
  • @durron597 Based on the implementation of both `containsKey` and `get`, actually there is a difference in performance if the key is null. `containsKey` calls the method `getEntry` who iterates over the entry set, as `get` does too (they're actually the same method, except `get` does a null check with the key and returns null if the key is null, while `getEntry` assigns a hash value of 0 if the submitted key is `null`, this particular case makes the difference). – Fritz Dec 03 '12 at 17:13
2

Your code is very messy.

  • do is a reserved keyword, do not use it as a method name.
  • a 'if' expression must return a boolean, not null.
  • myMap's initialization is not correctly written

Here is a working version :

import java.util.HashMap;

public class A {
    private HashMap<Character, Boolean> myMap;

    public A() {
        this.myMap = new HashMap<Character, Boolean>();
        String mychars = "asdfzxcvqwer";
        for ( char c : mychars.toCharArray() )
            myMap.put(c, true);
    }

    public String execute(String input) {
        StringBuilder output = new StringBuilder();
        for ( char c : input.toCharArray() )
        {
            if ( this.myMap.get(c) != null )
                output.append(c);
        }
        return output.toString();
    }


    public static void main(String[] args) {
        A test = new A();
        test.execute("abc");
    }
}
Jean-Philippe Briend
  • 3,455
  • 29
  • 41
1

Alternatively, you can use apache.commons.lang3 which checks for Boolean and handles null check BooleanUtils.isTrue(c)

Explanation:

There's a general confusion where exactly the NPE is being thrown i.e. when get() is called on the map or when if(...) is performed.

Your map is declared as:

myMap = new HashMap<Character, Boolean>();

Which contains a primitive boolean wrapper class Boolean as a value to the map entry.

When you do:

if (myMap.get(c))

myMap which is a HashMap returns null when get() is invoked because a certain key is not present in the map. null is then unboxed to primitive boolean and that's where the NPE is being thrown not when you invoke get() by itself.

Community
  • 1
  • 1
nabster
  • 1,561
  • 2
  • 20
  • 32
0

In my case I just handled it with a catch block , like so :

@PostMapping("/findAllLastExecutedApi")
    public ResponseEntity<Map<String,List<Results>>>findAllLastExecuted(@RequestBody Map<String,String> uuids) {
        try{ 
            // NPE is triggered here : 
            if(uuids.get("demoId").isEmpty()) {
                Map<String,List<Results>> badResults= Collections.singletonMap("Invalid demoId provided, is empty",null);
                log.error("Invalid demoId provided, is empty {}",uuids);
                return  ResponseEntity.ok(badResults);
            }

            Map<String,List<Results>> results =
                    this.service.findAll(uuids.get("demoId"));
            return ResponseEntity.ok(results);

        }catch (NullPointerException e){
            log.error("Invalid demoId provided, is null {}",uuids);
            throw new NullPointerException("Invalid demoId provided , is null");
        }
    }
Alferd Nobel
  • 3,185
  • 2
  • 30
  • 35