4

Following code is throwing NPE for the property Salary being null. class Person has properties: string: name, Integer: age, Integer: salary salary can be null here. I want to create a List of salaries.

persons.stream().mapToDouble(Person::getSalary).boxed().collect(Collectors.toList())
Here I must retain null values in the result list. null can not be replaced with 0.

Ousmane D.
  • 54,915
  • 8
  • 91
  • 126
Himanshu Yadav
  • 13,315
  • 46
  • 162
  • 291
  • Why not just `map(...)` to `Double`, taking `null` into account as appropriate? – Oliver Charlesworth Apr 05 '18 at 18:59
  • *Here I must retain* what possible could you do with more nulls? Unless retain should be remove – Eugene Apr 05 '18 at 19:02
  • @HadiJ Would `.filter(Objects::nonNull)` filter all the objects with any null property? – Himanshu Yadav Apr 05 '18 at 19:02
  • @HimanshuYadav of course not – Eugene Apr 05 '18 at 19:03
  • Not sure why it has been downvoted. – Himanshu Yadav Apr 05 '18 at 19:04
  • 1
    You first need to read the stack trace of the exception, as always. What causes it? Is the value null? Does getProperty() throw it? Is it a bug in that method? Is it a bug in the code you posted? What is the desired outcome? Start by answering all these questions. It's been downvoted because you didn't bother posting the stack trace and the relevant code, making your question unclear, and because it doesn't seem you've tried anything to fix the error by yourself. – JB Nizet Apr 05 '18 at 19:06
  • @HimanshuYadav The reason your question got downvoted is because you did no(t enough) research. [How much research effort is expected on SO? A lot.](https://meta.stackoverflow.com/questions/261592/how-much-research-effort-is-expected-of-stack-overflow-users) I found the duplicate with a google search, showing up as the topmost answer. – Turing85 Apr 05 '18 at 19:08
  • 5
    I don't think this is a duplicate - the OP wants to **retain** nulls, not filter them out. – Oliver Charlesworth Apr 05 '18 at 19:14
  • 1
    @Turing85 Thanks for the shoutout. But I did research before the asking the question. I must have spent more time on explaining the issue properly. – Himanshu Yadav Apr 05 '18 at 19:19
  • @OliverCharlesworth Thanks. Appreciate your support. People are posting their solutions without even reading the question completely. They just read the first line `NPE`, filter the null objects. Issue is not with the null objects but the null property which is being cast to null. – Himanshu Yadav Apr 05 '18 at 19:22
  • 4
    @HimanshuYadav this is not about us, but about you and the way you posted the question. A clear example to begin with would have made it a good question - which you have not provided – Eugene Apr 05 '18 at 19:22

2 Answers2

10

I think you could use map instead of mapToDouble along with the ternary operator:

List<Double> salaries = persons.stream()
    .map(Person::getSalary)
    .map(s -> s == null ? null : s.doubleValue())
    .collect(Collectors.toList())
fps
  • 33,623
  • 8
  • 55
  • 110
  • 1
    or `persons.stream() .map(p->(p.getProperty()!= null)?new Double(p.getProperty()):null) .collect(Collectors.toList());` – Hadi J Apr 05 '18 at 19:35
  • 2
    @HadiJ calling `getProperty()` twice doesn’t look like an improvement to me. Further, you should never use `new Double(…)`, use either auto-boxing or `Double.valueOf`. Starting with Java 9, the constructor has been marked as deprecated to remind you on this. If you want a single `map` step, you can use `.map(p -> Optional.ofNullable(p.getSalary()).map(Integer::doubleValue).orElse(null))` but I’d prefer the code of this answer. – Holger Apr 06 '18 at 09:30
3

If I understand correctly, you want to convert each property value to Double if it's non-null, or leave it as null if it's null. So just say so:

Integer prop = value.getProperty();
return (prop != null) ? prop.doubleValue() : null;

You can express that as a lambda, and pass it to map(). (Left as an exercise for the reader.)

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680