4

I often see in vavr-based code:

...
.map(x -> {
   if (someCondition(x)) {
      return doWith(x);
   } else {
     return x;
   }
})
...

Is there any way to eliminate this logic from map call using some constructs? I find this if condition awkward.

Opal
  • 81,889
  • 28
  • 189
  • 210

4 Answers4

4

Using the ternary conditional expression may look better:

.map(x -> someCondition(x) ? doWith(x) : x)
Eran
  • 387,369
  • 54
  • 702
  • 768
  • Actually, this changes nothing. Whether it's ternary of `if` statement doesn't matter. But thanks for the idea. – Opal Apr 19 '18 at 05:58
  • @Opal it reduces the length of the code. It eliminates the need to use curly braces and return statement. Hence I'd say it's less awkward than using `if`. – Eran Apr 19 '18 at 05:59
  • Yes, I see it, however this is not what I was looking for. What I'm looking for is some vavr or functional construct I don't know about. Yet ;) – Opal Apr 19 '18 at 06:07
  • What I'm looking for is a concept while what you suggested is just syntax. – Opal Apr 19 '18 at 06:45
  • @Opal I guess you were hoping for a Stream method such as `mapIf(Predicate,Function)`, but it doesn't exist. – Eran Apr 19 '18 at 06:51
  • Yes, it does not exist. That's why I'm asking how to replace it. – Opal Apr 19 '18 at 07:32
3

My idea would be to wrap x with optional

   .map(x -> Optional.ofNullable(x)
            .filter(this::someCondition)
            .map(this::doWith)
            .orElse(x))

And this returns Optional<X> so U need to handle it properly somewhere else

hanskoff
  • 182
  • 13
  • While this works, this is overkill, and more importantly, it doesn't carry the intention. Your code makes it hard to understand you want to conditionally transform the element. The ternary operator or if-else statement is more expressive. – Sir4ur0n Apr 21 '18 at 11:08
  • of course, for some it might be an overkill, but that is just mine/another approach to replace if-statement – hanskoff Apr 24 '18 at 08:07
2

Either use the ternary operator if the conditions do not contain any logic or very little

.map(x -> someCondition(x) ? doWith(x) : x)

Or extract the logic within the map in a method

.map(ClassName::myXTreatmentMethod)
// or
.map(this::myXTreatmentMethod)

With myXTreatmentMethod being

public X_Type myXTreatmentMethod(X_Type x) {
    if (someCondition(x)) {
        // some logic
        return doWith(x);
    }
    return x;
}
Yassin Hajaj
  • 21,337
  • 9
  • 51
  • 89
0

How about case-match like the following:

Iterator.range(0, 10)
        .map(index -> Match(index).of(
            Case($(n -> n % 2 == 0), "even"),
            Case($(), "odd")
        ))
Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
Kevin Ip
  • 21
  • 2