21

I have an object, Person, which has two properties Name and Status. From a list of objects I hope to filter out the Person objects with a status of In Progress. Here is my code:

personList.stream().filter(
    t -> t.getStatus().equalsIgnoreCase(
        "In Progress")).collect(Collectors.toList());

But the code is throwing a nullpointerexception error. When I checked, I saw that a few of the objects with In Progress status had null values. How do we handle this in lambda?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
sTg
  • 4,313
  • 16
  • 68
  • 115
  • 10
    You handle it juste like in any other code. It's better in this case to do "In Progress".equalsIgnoreCase(t.getStatus()) – JEY Oct 26 '17 at 09:53
  • 7
    The real question is what you want to happen when status is null. Do you want to filter those rows out? Include them? Fail with a meaningful message? Return false from the method? Null is an exceptional condition that requires thought and not some technical trick to ignore. If you don't want to put in that kind of thought, you should avoid letting status be null in the first place. – Reinstate Monica Oct 26 '17 at 14:39

4 Answers4

42

You can just reverse the 2 "operands" of the equals method:

"In Progress".equalsIgnoreCase(t.getStatus())

This way since "In Progress" can never be null, there won't be an NPE!

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • 3
    Yoda strikes back. Classic! – Eel Lee Oct 26 '17 at 15:07
  • 3
    This, _this_, and **this**. I have lost count the number of times I have fixed Java libraries' NPE (public and not) by merely using Yoda conditions. I wish there were a way to evangelize this just a bit more. – hunteke Oct 26 '17 at 15:16
  • 8
    @EelLee back strikes Yoda – Yakk - Adam Nevraumont Oct 26 '17 at 15:22
  • 1
    Or always use Objects.equals() instead of instance.equals() – Bob Brinks Oct 26 '17 at 15:23
  • @hunteke But you shouldn't blindly use them. – xehpuk Oct 26 '17 at 16:21
  • 3
    This hides the fact that there might be a `person` with an invalid status. [@TheRock3t](https://stackoverflow.com/users/1274061/therock3t) gave a better answer. – Igwe Kalu Oct 26 '17 at 17:11
  • 1
    @hunteke Yoda equality is terse but it removes not-null validation that should probably be there most of the time. Most variables in most programs should never be null. In the few cases where a variable can be null, yoda equality is handy, but it's a special tool for a special case. – Reinstate Monica Oct 26 '17 at 18:22
  • @Solomonoff'sSecret Perhaps; I'm always willing to concede to other's lived experience. However, my experience has ~never needed this sort of null check. Am I just lucky that I haven't been bitten in ~13 years? Maybe. But I stand by my point of the countless times I have fixed libraries and other code by Yoda conditions. Sometimes, the compiler caught the issue, other times it was logic exploitation like this, etc. In this case, I argue it's the correct thing to do, not the wrong thing. The sole condition is if `t` is `"In Progress"`. But that's all I can faithfully argue here: this case. – hunteke Oct 26 '17 at 18:33
  • @hunteke Fair enough. And conditionals are not the right place for null checks. But generally I like to program in a way that avoids nulls and is hostile to nulls so that the accidental null gets caught quickly. Perhaps you have a different style. – Reinstate Monica Oct 26 '17 at 19:10
25

Try filtering out objects with null statuses

personList
  .stream()
  .filter(t -> t.getStatus() != null)
  .filter(t -> t.getStatus().equalsIgnoreCase("In Progress"))
  .collect(Collectors.toList());
TheRock3t
  • 628
  • 9
  • 22
12

You can chain/merge filtering conditions to operate on non-null values with short-circuited conditions as:

personList.stream()
          .filter(t -> t.getStatus() != null && t.getStatus().equalsIgnoreCase("In Progress"))
          .collect(Collectors.toList());
Naman
  • 27,789
  • 26
  • 218
  • 353
4

Assuming for status = null, you won't select it. Then you can use "In Progress".equalsIgnoreCase(t.getStatus()) to avoid any possible null value in your status.

In whole,

personList.stream()
    .filter(t -> "In Progress".equalsIgnoreCase(t.getStatus()))
    .collect(Collectors.toList());
Alex
  • 803
  • 4
  • 9