• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • Liutauras Vilda
  • Jeanne Boyarsky
  • paul wheaton
Sheriffs:
  • Ron McLeod
  • Devaka Cooray
  • Henry Wong
Saloon Keepers:
  • Tim Holloway
  • Stephan van Hulst
  • Carey Brown
  • Tim Moores
  • Mikalai Zaikin
Bartenders:
  • Frits Walraven

Having nicer body for ifPresentOrElse

 
Ranch Hand
Posts: 36
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi everyone,
I am going to refactor the code below, to use .ifpresentOrElse()
I am wondering what is the best way to do that.
Here is the code (Naming is not important )




Here is the solution 1:




solution 2 is using AtomicRefrence:



I am wondering if there is any solution, nicer that AtomicRefrence of having an array-size 1 ?
p.s. not sure why, but even having MyDetail final wont help, compiler error

Thanks.
 
Saloon Keeper
Posts: 15731
368
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
 
Stephan van Hulst
Saloon Keeper
Posts: 15731
368
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I prefer this one though:

I'm not sure why you think using ifPresentOrElse() is an improvement.
 
Björn Björnsen
Ranch Hand
Posts: 36
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:



Wow,
Nice one,
Completely forgor about method chainig of optional values :-D
 
Björn Björnsen
Ranch Hand
Posts: 36
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:I prefer this one though:

I'm not sure why you think using ifPresentOrElse() is an improvement.



To make sure not getting NPE on data.get.
Also keep sonar happy 😊

But thanks, the second solution also looks nice.
 
Stephan van Hulst
Saloon Keeper
Posts: 15731
368
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Sonar is a tool that supports the developer. It's not your job to make Sonar happy, it's Sonar's job to make you happy.
 
Saloon Keeper
Posts: 10930
87
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Stephan, trying to follow your example. Does the "orElseThrow" pair up with the first ".map", the last, or any?
 
Master Rancher
Posts: 5060
81
  • Likes 3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
In Stephan's original code, the "orElseThrow()" really applies to all the map() calls, as well as the original db.getDatafor(XXX).  That is, if the original value was null, or if  any of the mapped functions returns null, then the Optional becomes an empty Optional, and all subsequent map() calls have no further effect, and the orElseThrow() will cause an exception to be thrown.  So an exception can be thrown due to a null from any of the mapped funtions.

In Stephan's later preferred code, the "orElseThrow()" applies only to the original db.getDataFor(XXX) call.  I assume he prefers that because it's clearer - that's the place we expect that an empty Optional might occur, and his code handles that clearly... and after that, there's really no need for Optional and map() any more.  So the second version is better at communicating intent.  

The only possible downside is, this assumes that none of the later methods used (like createDetail()) will return a null.  If they did, well, the second version would throw a NullPointerException, while the first version with multiple map() calls would work just fine. That might be a good idea, if you can't trust those later methods not to return null.  But it they are trustworthy, then the multiple map() calls are an unnecessary obfuscation.
 
Marshal
Posts: 79971
396
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Please remind us all why orElseThrow(XYZException::new) is better than orElseThrow(new XYZException()). I remember reading about that in Ken Kousen's book, and I think I know the answer.
 
Stephan van Hulst
Saloon Keeper
Posts: 15731
368
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Simply put, why create an object until you're definitely going to need it?
 
Stephan van Hulst
Saloon Keeper
Posts: 15731
368
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Another good reason might be that Optional doesn't contain a method orElseThrow(Throwable).
 
Campbell Ritchie
Marshal
Posts: 79971
396
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:. . . why create an object until you're definitely going to need it?

That is what I remember from previous reading.
 
Sheriff
Posts: 22815
132
Eclipse IDE Spring Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:Please remind us all why orElseThrow(XYZException::new) is better than orElseThrow(new XYZException()). I remember reading about that in Ken Kousen's book, and I think I know the answer.


orElseThrow comes in two overloads: one without arguments that throws a NoSuchElementException, and one with a supplier. In other words, orElseThrow(new XYZException()) doesn't even compile.
 
Campbell Ritchie
Marshal
Posts: 79971
396
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Stephan did mention that, Rob, but I found your explanation easier to understand.
 
Mike Simmons
Master Rancher
Posts: 5060
81
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:Please remind us all why orElseThrow(XYZException::new) is better than orElseThrow(new XYZException()). I remember reading about that in Ken Kousen's book, and I think I know the answer.


I think Ken's book probably addresses a different question, since the second code isn't even an option in the real world.  I can think of two variants that might have been worth discussing:

1. Why isn't orElseThrow(Throwable) provided as an option in the API?

2. Is there a reason to prefer orElseThrow(XYZException::new) instead of orElseThrow(() -> new XYZException())?

The first one was addressed by Stephan: it would require us to create the exception (and populate its stack trace, a somewhat time-consuming operation) whether or not anything actually went wrong.  That could potentially degrade performance for no good reason.  We don't want to create an exception unless we actually need it.

The second one is probably what Ken was talking about in his book.  In situations where we can use either a lambda expression or a method handle, is there any reason to prefer one or the other?  A lambda expression is more flexible, of course - you have more freedom to write arbitrary code into the expression.  Within some limits, of course.  I think the main benefit of using a method is performance... though I'm not sure how big a difference it really makes.  When you use a lambda expression, the compiler generates methods and/or nested class to contain the implementation.  Whereas if you use a method reference, it has the ability to calls the already-existing method more directly.  I'm not sure if there are any other benefits, though.
 
If we don't do the shopping, we won't have anything for dinner. And I've invited this tiny ad:
Gift giving made easy with the permaculture playing cards
https://coderanch.com/t/777758/Gift-giving-easy-permaculture-playing
reply
    Bookmark Topic Watch Topic
  • New Topic