-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;
    }
}
7
  • 1
    lambda is a function and if-else is.. if-else how do you want to replace a condition with a function? Commented Apr 7, 2020 at 7: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. Commented Apr 7, 2020 at 7: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??? Commented Apr 7, 2020 at 7: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? Commented Apr 7, 2020 at 7: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. Commented Apr 7, 2020 at 7:11

2 Answers 2

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);
Sign up to request clarification or add additional context in comments.

1 Comment

Starting with Java 9, you’d preferably use List<DataObj> dataObjs = Objects.requireNonNullElse(data.getDataObjs(), Collections.singletonList(data)); instead of the Optional
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
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.