-4

I don't understand what is happening here. Basically, my code looks something like this:

Double average = 0.;
for(Map<String, Double> map : model.getMaps()){
    average += map.get(key); // this line throws a NullPointerException
}
average /= model.getMaps().size();

If I then do:

Double average = 0.;
for(Map<String, Double> map : model.getMaps()){
    try{
        average += map.get(key); // this line throws a NullPointerException
    } catch(NullPointerException e){
        e.printStackTrace();
        System.out.println(map.get(key).toString());
    }
}
average /= model.getMaps().size();

It prints a number, not null. This is making me very confused.

More checks:

if(map==null) System.out.println("Map null");
else {
    if (map.get(key).toString() == null) {
         System.out.println(key + " null");
    } else {
        String newValS = map.get(key).toString(); //throws a NPE
    }
}

It is very weird that I checked for everything not being null and still it throws a NPE.

Pedro Victori
  • 75
  • 1
  • 10
  • 9
    `map` is null or `map.get(key)` returns null. Please include a [mre] and a stack trace in debugging questions. – khelwood Jan 22 '20 at 15:32
  • @khelwood they say `map.get(key)` prints a number when they catch the exception. But yeah, an MVC is needed. – Federico klez Culloca Jan 22 '20 at 15:34
  • 2
    As an aside: declare `average` as a `double` (not `Double`) to avoid repeated unboxing/boxing. – Andy Turner Jan 22 '20 at 15:36
  • That can't be it, because this line `System.out.println(map.get(key).toString());` does print an actual number, the correct one. I am not able to produce a minimal reproducible example without including the whole project. The stack trace is just java.lang.NullPointerException at the line I commented. – Pedro Victori Jan 22 '20 at 15:36
  • @PedroVictori you can't populate a map with the values that cause the error? That's what an MVC would be. – Federico klez Culloca Jan 22 '20 at 15:37
  • OK, I'm going to try. – Pedro Victori Jan 22 '20 at 15:38
  • 1
    Again, without [MCVE] (a.k.a. [SSCCE](http://sscce.org)) instead of debugging all we can do is guess which is not very efficient way of solving problems. Please take your time and spend it on creating such example, possibly while doing so you will find cause of the problem so IMO it is worth doing. – Pshemo Jan 22 '20 at 15:39
  • 1
    Another possibility is that in your **real** code, `average` is null, though that is impossible in the code you have posted. – khelwood Jan 22 '20 at 15:44
  • @Pshemo I'm working on it, my thinking was that the piece of code I posted seems impossible, like the same thing is null in one line and not null in the next, regardless of the actual values in the map. So I thought maybe there is some particularity in Java that I'm missing. @khelwood `average` is not null, and the same thing happens if I declare `average` as a `double` instead of `Double`. – Pedro Victori Jan 22 '20 at 15:51
  • The easiest thing to do would be to use the debugger to step through, but if you don't know how to do that, you could add print statements in the try just before the nullpointer line. – R Wri Jan 22 '20 at 15:55
  • Your checks are wrong. `if (map.get(key).toString() == null)` is not useful. `if (map.get(key)==null)` would be better. – khelwood Jan 22 '20 at 21:34
  • `if (map.get(key).toString() == null) {` what if `map.get(key)` is `null`? You would end up with `if (null.toString == null)` but `null` doesn't have *any* methods, not even `toString()` and in such case it throws NPE. – Pshemo Jan 22 '20 at 21:41

1 Answers1

0

Either map or the retrieved value is null (key does not exist in the map).

double sum = 0.0;
int count = 0;
for (Map<String, Double> map : model.getMaps()) {
    if (map != null) {
        Double value = map.get(key);
        if (value != null) {
            sum += value;
            ++count;
        }
    }
}
double average = count == 0 ? 0.0 : sum / count;

Streams

double average = model.getMaps().stream()
    .filter(Objects::nonNull)
    .map(m -> m.get(key))
    .filter(Objects::nonNull)
    .mapToDouble()
    .average().orElse(0.0);
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138