This article shows a way to combine Java 8 Optional and Stream to completely remove if else statements.
Let's look at some code:
public class ExpressionBuilder {
public String buildExpression(List<Integer> list1, List<Integer> list2) {
String expression = "";
String list1Expression = buildList1Expression(list1);
String list2Expression = buildList2Expression(list2);
if (list1Expression == null && list2Expression != null) {
expression = list2Expression;
}
if (list1Expression != null && list2Expression == null) {
expression = list1Expression;
}
if (list1Expression != null && list2Expression != null) {
expression = list1Expression + " and " + list2Expression;
}
return expression;
}
private String buildList1Expression(List<Integer> list1) {
String expression = null;
if (list1 != null && !list1.isEmpty()) {
expression = "(";
for (int i = 0; i < list1.size(); i++) {
if (i != list1.size() - 1) {
expression = expression + "list1:" + list1.get(i) + " or ";
} else {
expression = expression + "list1:" + list1.get(i);
}
}
expression = expression + ")";
}
return expression;
}
private String buildList2Expression(List<Integer> list2) {
String expression = null;
if (list2 != null && !list2.isEmpty()) {
expression = "!(";
for (int i = 0; i < list2.size(); i++) {
if (i != list2.size() - 1) {
expression = expression + "list2:" + list2.get(i) + " or ";
} else {
expression = expression + "list2:" + list2.get(i);
}
}
expression = expression + ")";
}
return expression;
}
}
The code above will convert two list of Integers into a String. For example, if you have:list1 = 10, 20, 30
list2 = 40, 50, 60, 70
The result would be:
"(list1:10 or list1:20 or list1:30) and !(list2:40 or list2:50 or list2:60 or list2:70)"
If you only have list1:
list1 = 10, 20, 30
Then the result would be:
"(list1:10 or list1:20 or list1:30)"
If you only have list2:
list2 = 40, 50, 60, 70
Then the result would be:
"!(list2:40 or list2:50 or list2:60 or list2:70)"
The code needs to handle the following cases:
- list1 is null
- list1 is empty
- list1 has only 1 element
- list2 is null
- list2 is empty
- list2 has only 1 element
Let's look how Java 8 Optional and Stream can help in this case:
public class Java8ExpressionBuilder {
public String buildExpression(List<Integer> list1, List<Integer> list2) {
return Stream.of(buildList1Expression(list1), buildList2Expression(list2))
.filter(op -> op.isPresent())
.map(op -> op.get())
.reduce((result, s) -> result + " and " + s).orElse("");
}
private Optional<String> buildList1Expression(List<Integer> list1) {
return Optional.ofNullable(list1).flatMap(list -> list.stream()
.map(i -> "list1:" + i)
.reduce((result, s) -> result + " or " + s)
.map(s -> "(" + s + ")"));
}
private Optional<String> buildList2Expression(List<Integer> list2) {
return Optional.ofNullable(list2).flatMap(list -> list.stream()
.map(i -> "list2:" + i)
.reduce((result, s) -> result + " or " + s)
.map(s -> "!(" + s + ")"));
}
}
A couple of things worth mentioning here: - The reduce method is very good for concatenating a list of elements into a single String.
- Put two Optionals into a Stream so that Stream Api and Optional Api can be used together.
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
public class Java8ExpressionBuilder {
public String buildExpression(List<Integer> list1, List<Integer> list2) {
return Stream.of(buildList1Expression(list1), buildList2Expression(list2))
.filter(op -> op.isPresent()).map(op -> op.get())
.reduce((result, s) -> result + " and " + s).orElse("");
}
private Optional<String> buildList1Expression(List<Integer> list1) {
return Optional.ofNullable(list1).flatMap(
list -> list.stream().map(i -> new StringBuilder("list1:")
.append(i)).reduce((result, s) -> result.append(" or ").append(s))
.map(s -> "(" + s.toString() + ")"));
}
private Optional<String> buildList2Expression(List<Integer> list2) {
return Optional.ofNullable(list2).flatMap(
list -> list.stream().map(i -> new StringBuilder("list2:")
.append(i)).reduce((result, s) -> result.append(" or ").append(s))
.map(s -> "!(" + s.toString() + ")"));
}
}
No comments:
Post a Comment