-2

I want to replace conventional if else with lambda. Consider following highlighted code, is there some simple way to have this represented with Lambda ?

public class IfElseLambda {

    public static void main(String[] args) {

        String value = null;
        DataObj data = new DataObj();

        List<DataObj> dataObjs = data.getDataObjs();

        ***if (dataObjs != null) {

            value = dataObjs.stream().map(dataObject -> getValue(dataObject)).filter(Objects::nonNull).findFirst().orElse(null);
        } else {
            value = getValue(data);
        }***

    }


    public static String getValue(DataObj dataObj) {
        return "Get value from dataObj";
    }
}

class DataObj {
    List<DataObj> dataObjs;

    public List<DataObj> getDataObjs() {
        return dataObjs;
    }

    public void setDataObjs(List<DataObj> dataObjs) {
        this.dataObjs = dataObjs;
    }
}
Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
JavaBuilder
  • 149
  • 9
  • 1
    `lambda` is a function and `if-else` is.. `if-else` how do you want to replace a condition with a function? – Omri Attiya Apr 07 '20 at 07:00
  • I see no good way to replace `if-else` with lambda. If it's because you don't like `if-else`, use a `? :` ternary operator. – Andreas Apr 07 '20 at 07:01
  • @Andreas Even with ternary operation, you'd be replacing if-else with that ternary operation... lambda simply cannot do that. Even if you have a function which accepts two lambdas and a condition, you would still have to have a branching pattern somewhere. In some lower-level language you could theoretically put two pointers to lambdas in an array, then use pointer arithmetic to figure out which one to call. But ... WHY??? – v010dya Apr 07 '20 at 07:07
  • 3
    Not only how would you want to do that, but why? `if-else` is a basic, well-known construct. Why would you want to overengineer it into a lambda? – PaianganuOm Apr 07 '20 at 07:07
  • @v010dya Seems you totally misunderstood my comment. I said to use ternary operator instead of `if-else`, which means e.g. `value = (dataObjs == null ? getValue(data) : dataObjs.stream()...findFirst().orElse(null));` --- See, no `if-else`. – Andreas Apr 07 '20 at 07:11
  • @Andreas Exactly, you have replaced if-else with ternary operator... not with a lambda. – v010dya Apr 07 '20 at 07:12
  • @v010dya I already said "no good ... lambda", and now paraphrasing the rest: "but you can use ternary operator **instead** of lambda to eliminate `if-else`". I never claimed that the ternary operator is a lambda. – Andreas Apr 07 '20 at 07:15

2 Answers2

2

One thing you can do is to change the null list to something which results in the same output:

List<DataObj> dataObjs = Optional.ofNullable(data.getDataObjs()).orElse(Collections.singletonList(data));

dataObjs will now be a list with a single element in the case that data.getDataObjs() is null.

Now you don't need the if/else:

value = dataObjs.stream().map(dataObject -> getValue(dataObject)).filter(Objects::nonNull).findFirst().orElse(null);
Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • 1
    Starting with Java 9, you’d preferably use `List dataObjs = Objects.requireNonNullElse(data.getDataObjs(), Collections.singletonList(data));` instead of the `Optional` – Holger Apr 07 '20 at 09:49
0

I your aim is to isolate the logic of your if-else, and potentially allowing it to be replaced, maybe you could do the following : Your lambda take as input your data list, and gives you back a String value. Therefore, you can use a java.util.Function interface, like this:

Function<List<DataObj>, String> extractor = dataList 
    -> dataList == null? Stream.of(DEFAULT_DATA_OBJ) : dataList.stream()
       .map(dataObject -> getValue(dataObject))
       .filter(Objects::nonNull)
       .findFirst()
       .orElse(null)

Note, you still have a ternary operator (Do not see how you could do without it, because if your list can be null, you cannot even use Stream.concat to protect from empty-list). However, with that construct, the logic of your ternary operator is replaceable if you make the extractor function replaceable in your code.

Exemple:

public static void main(String... args) {

    final List<DataObj> dataList = ...;
    final DataObj defaultValue = ...;

    Function<List<DataObj>, String> extractor = dataList 
        -> dataList == null? Stream.of(defaultValue) : dataList.stream()
           .map(dataObject -> getValue(dataObject))
           .filter(Objects::nonNull)
           .findFirst()
           .orElse(null);

    doStuff(dataList, extractor);

    // Now, if you want to change your extraction logic, do
    doStuff(dataList, whatever -> "Return a constant title");
}

public static void doStuff(final List<DataObj> dataList, final Function<List<DataObj, String> titleExtractor) {
   // Do stuff here
}
amanin
  • 3,436
  • 13
  • 17