4

In Java 8,

I currently have a lambda that looks like this:

.createSomething((acceptableStates, someProxy) -> (userId) ->   
    acceptableStates.contains(someProxy.getSomeAttributeId(userId)))

However, we have changed someProxy.getSomeAttributeId to return an Optional<String> instead of a string.

What's the cleanest / most accepted way to essentially check for if acceptableStates contains the value of someProxy.getSomeAttributeId(userId) if the attribute returned isn't empty?

(Note: acceptableStates is still a list of strings, not of Optional<String>)

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
CustardBun
  • 3,457
  • 8
  • 39
  • 65

4 Answers4

9
.... userId -> someProxy.getSomeAttributeId(userId)
                        .map(acceptableStates::contains)
                        .orElse(Boolean.FALSE);
Eugene
  • 117,005
  • 15
  • 201
  • 306
  • This may be obvious, but what is the reason for using Boolean.FALSE over just "false"? – CustardBun Jul 26 '17 at 20:13
  • 1
    @Mei probably no reason for your case... just wanted to make that obvious, could be easily replace with plain `false` – Eugene Jul 26 '17 at 20:15
2

Unfortunately, I see no very clean solution here. Refer to this question: Functional style of Java 8's Optional.ifPresent and if-not-Present?

Additionally, you even have to save the optional in a variable if the call to getSomeAttributeId does cost resources.

.createSomething((acceptableIds, someProxy) -> (userId) ->
    {
       Optional<String> attrId = someProxy.getSomeAttributeId(userId);
       return attrId.isPresent() ? acceptableStates.contains(attrId.get()) : false;
    })
A1m
  • 2,897
  • 2
  • 24
  • 39
  • 1
    `condition1? condition2: false` means `condition1 && condition2`, see also [here](https://stackoverflow.com/questions/45335722/calling-contains-on-a-list-for-an-optional-value-in-java/45336092#comment77665018_45336011)… – Holger Jul 27 '17 at 13:19
  • Good catch, I agree. But I wouldn't say that necessarily adds to readability. I would keep `?` since the intention is more clear. – A1m Jul 27 '17 at 20:21
2

I strongly recommend writing understandable and clear code like this snippet:

Optional<SomeAttributeId> optional = someProxy.getSomeAttributeId(userId);

return optional.isPresent() && acceptableStates.contains(optional.get‌​());

If there should not be thrown an exception (1) when someProxy.getSomeAttributeId(userId) is an empty optional:

acceptableStates.contains(someProxy.getSomeAttributeId(userId).orElseThrow(() -> new Exception()))

Or unless you have the default value (2) to fill up the result with:

acceptableStates.contains(someProxy.getSomeAttributeId(userId).orElse(DEFAUT_VALUE))

My point:

Do not pursue Java 8 features which will mess everything up, especially in cases where a simple boolean expression could be used. I had experience refactoring some code toward plain Java statements because new people (1.1) came in a project could not get what the code does. With the time, even I (as a writer) barely can do so (1.2).

Also, with that "lambda chain" style, one slight change could cause rewriting a snippet/method entirely (2).

It is always fun to poke around n-nested lambdas, where n > 2 (3).


Anyway, if you don't share my point, @Eugene proposed a good way to go with.

Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
  • 1
    Every time you see a boolean literal in a compound expression, you can be sure that there is an (usually simpler) alternative without, `optional.isPresent()? acceptableStates.contains(optional.get()): false;` can be replaced by `optional.isPresent()&&acceptableStates.contains(optional.get())` – Holger Jul 27 '17 at 13:17
0
return value.isPresent() && value.get().contains("some-text");
Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
Uday
  • 149
  • 6