In Java 8, I want to do something to an Optional object if it is present, and do another thing if it is not present.
if (opt.isPresent()) {
System.out.println("found");
} else {
System.out.println("Not found");
}
This is not a 'functional style', though.
Optional has an ifPresent() method, but I am unable to chain an orElse() method.
Thus, I cannot write:
opt.ifPresent( x -> System.out.println("found " + x))
.orElse( System.out.println("NOT FOUND"));
In reply to #assylias, I don't think Optional.map() works for the following case:
opt.map( o -> {
System.out.println("while opt is present...");
o.setProperty(xxx);
dao.update(o);
return null;
}).orElseGet( () -> {
System.out.println("create new obj");
dao.save(new obj);
return null;
});
In this case, when opt is present, I update its property and save to the database. When it is not available, I create a new obj and save to the database.
Note in the two lambdas I have to return null.
But when opt is present, both lambdas will be executed. obj will be updated, and a new object will be saved to the database . This is because of the return null in the first lambda. And orElseGet() will continue to execute.
If you are using Java 9+, you can use ifPresentOrElse() method:
opt.ifPresentOrElse(
value -> System.out.println("Found: " + value),
() -> System.out.println("Not found")
);
For me the answer of #Dane White is OK, first I did not like using Runnable but I could not find any alternatives.
Here another implementation I preferred more:
public class OptionalConsumer<T> {
private Optional<T> optional;
private OptionalConsumer(Optional<T> optional) {
this.optional = optional;
}
public static <T> OptionalConsumer<T> of(Optional<T> optional) {
return new OptionalConsumer<>(optional);
}
public OptionalConsumer<T> ifPresent(Consumer<T> c) {
optional.ifPresent(c);
return this;
}
public OptionalConsumer<T> ifNotPresent(Runnable r) {
if (!optional.isPresent()) {
r.run();
}
return this;
}
}
Then:
Optional<Any> o = Optional.of(...);
OptionalConsumer.of(o).ifPresent(s -> System.out.println("isPresent " + s))
.ifNotPresent(() -> System.out.println("! isPresent"));
Update 1:
the above solution for the traditional way of development when you have the value and want to process it but what if I want to define the functionality and the execution will be then, check below enhancement;
public class OptionalConsumer<T> implements Consumer<Optional<T>> {
private final Consumer<T> c;
private final Runnable r;
public OptionalConsumer(Consumer<T> c, Runnable r) {
super();
this.c = c;
this.r = r;
}
public static <T> OptionalConsumer<T> of(Consumer<T> c, Runnable r) {
return new OptionalConsumer(c, r);
}
#Override
public void accept(Optional<T> t) {
if (t.isPresent()) {
c.accept(t.get());
}
else {
r.run();
}
}
Then could be used as:
Consumer<Optional<Integer>> c = OptionalConsumer.of(
System.out::println,
() -> System.out.println("Not fit")
);
IntStream.range(0, 100)
.boxed()
.map(i -> Optional.of(i)
.filter(j -> j % 2 == 0))
.forEach(c);
In this new code you have 3 things:
can define the functionality before the existing of an object easy.
not creating object reference for each Optional, only one, you have so less memory than less GC.
it is implementing consumer for better usage with other components.
By the way, now its name is more descriptive it is actually Consumer<Optional<?>>
Java 9 introduces
ifPresentOrElse if a value is present, performs the given action with the value, otherwise performs the given empty-based action.
See excellent Optional in Java 8 cheat sheet.
It provides all answers for most use cases.
Short summary below
ifPresent() - do something when Optional is set
opt.ifPresent(x -> print(x));
opt.ifPresent(this::print);
filter() - reject (filter out) certain Optional values.
opt.filter(x -> x.contains("ab")).ifPresent(this::print);
map() - transform value if present
opt.map(String::trim).filter(t -> t.length() > 1).ifPresent(this::print);
orElse()/orElseGet() - turning empty Optional to default T
int len = opt.map(String::length).orElse(-1);
int len = opt.
map(String::length).
orElseGet(() -> slowDefault()); //orElseGet(this::slowDefault)
orElseThrow() - lazily throw exceptions on empty Optional
opt.
filter(s -> !s.isEmpty()).
map(s -> s.charAt(0)).
orElseThrow(IllegalArgumentException::new);
An alternative is:
System.out.println(opt.map(o -> "Found")
.orElse("Not found"));
I don't think it improves readability though.
Or as Marko suggested, use a ternary operator:
System.out.println(opt.isPresent() ? "Found" : "Not found");
Another solution would be to use higher-order functions as follows
opt.<Runnable>map(value -> () -> System.out.println("Found " + value))
.orElse(() -> System.out.println("Not Found"))
.run();
There isn't a great way to do it out of the box. If you want to be using your cleaner syntax on a regular basis, then you can create a utility class to help out:
public class OptionalEx {
private boolean isPresent;
private OptionalEx(boolean isPresent) {
this.isPresent = isPresent;
}
public void orElse(Runnable runner) {
if (!isPresent) {
runner.run();
}
}
public static <T> OptionalEx ifPresent(Optional<T> opt, Consumer<? super T> consumer) {
if (opt.isPresent()) {
consumer.accept(opt.get());
return new OptionalEx(true);
}
return new OptionalEx(false);
}
}
Then you can use a static import elsewhere to get syntax that is close to what you're after:
import static com.example.OptionalEx.ifPresent;
ifPresent(opt, x -> System.out.println("found " + x))
.orElse(() -> System.out.println("NOT FOUND"));
If you can use only Java 8 or lower:
1) if you don't have spring-data the best way so far is:
opt.<Runnable>map(param -> () -> System.out.println(param))
.orElse(() -> System.out.println("no-param-specified"))
.run();
Now I know it's not so readable and even hard to understand for someone, but looks fine for me personally and I don't see another nice fluent way for this case.
2) if you're lucky enough and you can use spring-data the best way is
Optionals#ifPresentOrElse:
Optionals.ifPresentOrElse(opt, System.out::println,
() -> System.out.println("no-param-specified"));
If you can use Java 9, you should definitely go with:
opt.ifPresentOrElse(System.out::println,
() -> System.out.println("no-param-specified"));
You cannot call orElse after ifPresent, the reason is, orElse is called on an optiional but ifPresent returns void. So the best approach to achieve is ifPresentOrElse.
It could be like this:
op.ifPresentOrElse(
(value)
-> { System.out.println(
"Value is present, its: "
+ value); },
()
-> { System.out.println(
"Value is empty"); });
The described behavior can be achieved by using Vavr (formerly known as Javaslang), an object-functional library for Java 8+, that implements most of Scala constructs (being Scala a more expressive language with a way richer type system built on JVM). It is a very good library to add to your Java projects to write pure functional code.
Vavr provides the Option monad that provides functions to work with the Option type such as:
fold: to map the value of the option on both cases (defined/empty)
onEmpty: allows to execute a Runnable when option is empty
peek: allows to consume the value of the option (when defined).
and it is also Serializable on the contrary of Optional which means you can safely use it as method argument and instance member.
Option follows the monad laws at difference to the Java's Optional "pseudo-monad" and provides a richer API. And of course you can make it from a Java's Optional (and the other way around): Option.ofOptional(javaOptional) –Vavr is focused on interoperability.
Going to the example:
// AWESOME Vavr functional collections (immutable for the gread good :)
// fully convertible to Java's counterparts.
final Map<String, String> map = Map("key1", "value1", "key2", "value2");
final Option<String> opt = map.get("nonExistentKey"); // you're safe of null refs!
final String result = opt.fold(
() -> "Not found!!!", // Option is None
val -> "Found the value: " + val // Option is Some(val)
);
Moreover, all Vavr types are convertible to its Java counterparts, for the sake of the example: Optional javaOptional = opt.toJava(), very easy :) Of course the conversion also exists in the other way: Option option = Option.ofOptional(javaOptional).
N.B. Vavr offers a io.vavr.API class with a lot of convenient static methods =)
Further reading
Null reference, the billion dollar mistake
N.B. This is only a very little example of what Vavr offers (pattern matching, streams a.k.a. lazy evaluated lists, monadic types, immutable collections,...).
The problem here:
optional
.map(object -> {
System.out.println("If present.");
return null;
})
.orElseGet( () -> {
System.out.println("If empty.");
return null;
});
Is that map() converts the null returned by the first function to empty(); it then returns empty(). As it returns empty(), it prompts the invocation of the second function. Note that orElseGet() does not convert the null returned by the second function to empty(), so it will return null.
See the implementation of map():
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value));
}
}
And the implementation of orElseGet():
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
Thus when executed:
if optional.isPresent(), the system will print If present., then If empty., and the expression will evaluate to null.
if !optional.isPresent(), the system will print If empty., and the expression will evaluate to null.
If the function provided to map() returned any other value - any other value - the code would work as you expect, with the function provided to map() being executed if isPresent() and the function provided to orElseGet() if !isPresent():
For example, this:
optional
.map(data -> {
System.out.println("If present.");
return 0;
})
.orElseGet( () -> {
System.out.println("If empty.");
return 0;
});
When executed:
if optional.isPresent(), the system will print If present., and the expression will evaluate to 0.
if !optional.isPresent(), the system will print If empty., and the expression will evaluate to 0.
If your specific case, I suggest that your insert and update methods return, say, the persisted object, or the id of the persisted object, or something similarly useful; then you can use code similar to this:
final Object persist = optional
.map(object -> {
System.out.println("If present.");
return update(object);
})
.orElseGet( () -> {
System.out.println("If empty.");
return insert(new Object());
});
Another solution could be following:
This is how you use it:
final Opt<String> opt = Opt.of("I'm a cool text");
opt.ifPresent()
.apply(s -> System.out.printf("Text is: %s\n", s))
.elseApply(() -> System.out.println("no text available"));
Or in case you in case of the opposite use case is true:
final Opt<String> opt = Opt.of("This is the text");
opt.ifNotPresent()
.apply(() -> System.out.println("Not present"))
.elseApply(t -> /*do something here*/);
This are the ingredients:
Little modified Function interface, just for the "elseApply" method
Optional enhancement
A little bit of curring :-)
The "cosmetically" enhanced Function interface.
#FunctionalInterface
public interface Fkt<T, R> extends Function<T, R> {
default R elseApply(final T t) {
return this.apply(t);
}
}
And the Optional wrapper class for enhancement:
public class Opt<T> {
private final Optional<T> optional;
private Opt(final Optional<T> theOptional) {
this.optional = theOptional;
}
public static <T> Opt<T> of(final T value) {
return new Opt<>(Optional.of(value));
}
public static <T> Opt<T> of(final Optional<T> optional) {
return new Opt<>(optional);
}
public static <T> Opt<T> ofNullable(final T value) {
return new Opt<>(Optional.ofNullable(value));
}
public static <T> Opt<T> empty() {
return new Opt<>(Optional.empty());
}
private final BiFunction<Consumer<T>, Runnable, Void> ifPresent = (present, notPresent) -> {
if (this.optional.isPresent()) {
present.accept(this.optional.get());
} else {
notPresent.run();
}
return null;
};
private final BiFunction<Runnable, Consumer<T>, Void> ifNotPresent = (notPresent, present) -> {
if (!this.optional.isPresent()) {
notPresent.run();
} else {
present.accept(this.optional.get());
}
return null;
};
public Fkt<Consumer<T>, Fkt<Runnable, Void>> ifPresent() {
return Opt.curry(this.ifPresent);
}
public Fkt<Runnable, Fkt<Consumer<T>, Void>> ifNotPresent() {
return Opt.curry(this.ifNotPresent);
}
private static <X, Y, Z> Fkt<X, Fkt<Y, Z>> curry(final BiFunction<X, Y, Z> function) {
return (final X x) -> (final Y y) -> function.apply(x, y);
}
}
This should do the trick and could serve as a basic template how to deal with such requirements.
The basic idea here is following. In a non functional style programming world you would probably implement a method taking two parameter where the first is a kind of runnable code which should be executed in case the value is available and the other parameter is the runnable code which should be run in case the value is not available. For the sake of better readability, you can use curring to split the function of two parameter in two functions of one parameter each. This is what I basically did here.
Hint: Opt also provides the other use case where you want to execute a piece of code just in case the value is not available. This could be done also via Optional.filter.stuff but I found this much more readable.
Hope that helps!
Additional Info:
There is another way to have say "if then else" using currying:
public static <X, Y> Function<Predicate<X>, Function<Function<X, Y>, Function<Function<X, Y>, Y>>> ifThenElse(X input) {
return (final Predicate<X> pred) -> (final Function<X, Y> ifPresent) -> (final Function<X, Y> ifNotPresent) -> pred.test(input) ? ifPresent.apply(input) : ifNotPresent.apply(input);
}
This way it is possible to say:
final String result = ifThenElse("fancy")
.apply(input -> input.contains("fancy")) /* test */
.apply(input -> input.toUpperCase()) /* if-case */
.apply(input -> input.toLowerCase()); /* else-case */
In case you want store the value:
Pair.of<List<>, List<>> output = opt.map(details -> Pair.of(details.a, details.b))).orElseGet(() -> Pair.of(Collections.emptyList(), Collections.emptyList()));
Supposing that you have a list and avoiding the isPresent() issue (related with optionals) you could use .iterator().hasNext() to check if not present.
Related
I try to make a code more compact by coding a helper method, because the code is very repetitive.
The code consists of:
call a command (remote ssh, or local command, this part is not interesting for my question)
check if it was a success
if not, stop here and return the return code to the calling method (i.e. return cr;)
if success, continue with another command
I tried to create a helper method that do all that. If the command execution is a failure, it will return an Optional<Integer> of the return code. If it works as expected, it returns a Optional.empty().
My question is how to do something like that:
public void topMethod()
{
int cr = execCmds();
... do stuff with cr ...
}
private int execCmds()
{
executeCmd("my command").ifPresent(cr -> return cr);
executeCmd("my next command").ifPresent(cr -> return cr);
....
return 0;
}
As you can see, I want to stop the flow if the return code is meaningful. If not it must continue. Is there a way to do that? (Something concise.)
For information, the return cr is invalid in the ifPresent lambda method.
Use Optional.or()
Optional.or() was introduced with JDK 9, and expects a Supplier of Optional.
In a nutshell, method or() checks whether the Optional on which it is applied is empty, and if that's the case it replaces it with another optional. otherwise, if value is present, it would return the same optional (i.e. Supplier passed as an argument wouldn't be executed, functions are evaluated lazily).
public void topMethod() {
int cr = execCmds();
// do something with cr
}
private int execCmds() {
return executeCmd("my command")
.or(() -> executeCmd("my next command"))
.or(...) // more alternatives
.orElse(0);
}
public Optional<Integer> executeCmd(String command) {
return // something;
}
Stream of Suppliers
Another option would be to create a Stream of Supplier of Optional.
It can be useful if you're using JDK 8 (and therefor can't use or), or if executeCmd() returns an OptionalInt which lacks method or().
Stream would process each Supplier lazily, one at a time, and As well as in the previous solution each executeCmd() invocation would occur only if needed (if the previous command failed to provide the result).
Here's how it can be implemented:
public void topMethod() {
int cr = execCmds();
// do something with cr
}
private int execCmds() {
return Stream.<Supplier<OptionalInt>>of(
() -> executeCmd("my command"),
() -> executeCmd("my next command")
// ...
) // Stream<Supplier<OptionalInt>>>
.map(Supplier::get) // Stream<<OptionalInt>>
.filter(OptionalInt::isPresent) // Stream<<OptionalInt>>
.mapToInt(OptionalInt::getAsInt) // IntStream
.findFirst() // OptionalInt
.orElse(0);
}
public OptionalInt executeCmd(String command) {
return // something;
}
Would chaining your commands with or work? Something like
private int execCmds()
{
return executeCmd("command one")
.or(() -> executeCmd("command two")
.or(() -> executeCmd("command three")
.orElse(0);
}
With Java 8, I have this code:
if(element.exist()){
// Do something
}
I want to convert to lambda style,
element.ifExist(el -> {
// Do something
});
with an ifExist method like this:
public void ifExist(Consumer<Element> consumer) {
if (exist()) {
consumer.accept(this);
}
}
But now I have else cases to call:
element.ifExist(el -> {
// Do something
}).ifNotExist(el -> {
// Do something
});
I can write a similar ifNotExist, and I want they are mutually exclusive (if the exist condition is true, there is no need to check ifNotExist, because sometimes, the exist() method takes so much workload to check), but I always have to check two times. How can I avoid that?
Maybe the "exist" word make someone misunderstand my idea. You can imagine that I also need some methods:
ifVisible()
ifEmpty()
ifHasAttribute()
Many people said that this is bad idea, but:
In Java 8 we can use lambda forEach instead of a traditional for loop. In programming for and if are two basic flow controls. If we can use lambda for a for loop, why is using lambda for if bad idea?
for (Element element : list) {
element.doSomething();
}
list.forEach(Element::doSomething);
In Java 8, there's Optional with ifPresent, similar to my idea of ifExist:
Optional<Elem> element = ...
element.ifPresent(el -> System.out.println("Present " + el);
And about code maintenance and readability, what do you think if I have the following code with many repeating simple if clauses?
if (e0.exist()) {
e0.actionA();
} else {
e0.actionB();
}
if (e1.exist()) {
e0.actionC();
}
if (e2.exist()) {
e2.actionD();
}
if (e3.exist()) {
e3.actionB();
}
Compare to:
e0.ifExist(Element::actionA).ifNotExist(Element::actionB);
e1.ifExist(Element::actionC);
e2.ifExist(Element::actionD);
e3.ifExist(Element::actionB);
Which is better? And, oops, do you notice that in the traditional if clause code, there's a mistake in:
if (e1.exist()) {
e0.actionC(); // Actually e1
}
I think if we use lambda, we can avoid this mistake!
As it almost but not really matches Optional, maybe you might reconsider the logic:
Java 8 has a limited expressiveness:
Optional<Elem> element = ...
element.ifPresent(el -> System.out.println("Present " + el);
System.out.println(element.orElse(DEFAULT_ELEM));
Here the map might restrict the view on the element:
element.map(el -> el.mySpecialView()).ifPresent(System.out::println);
Java 9:
element.ifPresentOrElse(el -> System.out.println("Present " + el,
() -> System.out.println("Not present"));
In general the two branches are asymmetric.
It's called a 'fluent interface'. Simply change the return type and return this; to allow you to chain the methods:
public MyClass ifExist(Consumer<Element> consumer) {
if (exist()) {
consumer.accept(this);
}
return this;
}
public MyClass ifNotExist(Consumer<Element> consumer) {
if (!exist()) {
consumer.accept(this);
}
return this;
}
You could get a bit fancier and return an intermediate type:
interface Else<T>
{
public void otherwise(Consumer<T> consumer); // 'else' is a keyword
}
class DefaultElse<T> implements Else<T>
{
private final T item;
DefaultElse(final T item) { this.item = item; }
public void otherwise(Consumer<T> consumer)
{
consumer.accept(item);
}
}
class NoopElse<T> implements Else<T>
{
public void otherwise(Consumer<T> consumer) { }
}
public Else<MyClass> ifExist(Consumer<Element> consumer) {
if (exist()) {
consumer.accept(this);
return new NoopElse<>();
}
return new DefaultElse<>(this);
}
Sample usage:
element.ifExist(el -> {
//do something
})
.otherwise(el -> {
//do something else
});
You can use a single method that takes two consumers:
public void ifExistOrElse(Consumer<Element> ifExist, Consumer<Element> orElse) {
if (exist()) {
ifExist.accept(this);
} else {
orElse.accept(this);
}
}
Then call it with:
element.ifExistOrElse(
el -> {
// Do something
},
el -> {
// Do something else
});
The problem
(1) You seem to mix up different aspects - control flow and domain logic.
element.ifExist(() -> { ... }).otherElementMethod();
^ ^
control flow method business logic method
(2) It is unclear how methods after a control flow method (like ifExist, ifNotExist) should behave. Should they be always executed or be called only under the condition (similar to ifExist)?
(3) The name ifExist implies a terminal operation, so there is nothing to return - void. A good example is void ifPresent(Consumer) from Optional.
The solution
I would write a fully separated class that would be independent of any concrete class and any specific condition.
The interface is simple, and consists of two contextless control flow methods - ifTrue and ifFalse.
There can be a few ways to create a Condition object. I wrote a static factory method for your instance (e.g. element) and condition (e.g. Element::exist).
public class Condition<E> {
private final Predicate<E> condition;
private final E operand;
private Boolean result;
private Condition(E operand, Predicate<E> condition) {
this.condition = condition;
this.operand = operand;
}
public static <E> Condition<E> of(E element, Predicate<E> condition) {
return new Condition<>(element, condition);
}
public Condition<E> ifTrue(Consumer<E> consumer) {
if (result == null)
result = condition.test(operand);
if (result)
consumer.accept(operand);
return this;
}
public Condition<E> ifFalse(Consumer<E> consumer) {
if (result == null)
result = condition.test(operand);
if (!result)
consumer.accept(operand);
return this;
}
public E getOperand() {
return operand;
}
}
Moreover, we can integrate Condition into Element:
class Element {
...
public Condition<Element> formCondition(Predicate<Element> condition) {
return Condition.of(this, condition);
}
}
The pattern I am promoting is:
work with an Element;
obtain a Condition;
control the flow by the Condition;
switch back to the Element;
continue working with the Element.
The result
Obtaining a Condition by Condition.of:
Element element = new Element();
Condition.of(element, Element::exist)
.ifTrue(e -> { ... })
.ifFalse(e -> { ... })
.getOperand()
.otherElementMethod();
Obtaining a Condition by Element#formCondition:
Element element = new Element();
element.formCondition(Element::exist)
.ifTrue(e -> { ... })
.ifFalse(e -> { ... })
.getOperand()
.otherElementMethod();
Update 1:
For other test methods, the idea remains the same.
Element element = new Element();
element.formCondition(Element::isVisible);
element.formCondition(Element::isEmpty);
element.formCondition(e -> e.hasAttribute(ATTRIBUTE));
Update 2:
It is a good reason to rethink the code design. Neither of 2 snippets is great.
Imagine you need actionC within e0.exist(). How would the method reference Element::actionA be changed?
It would be turned back into a lambda:
e0.ifExist(e -> { e.actionA(); e.actionC(); });
unless you wrap actionA and actionC in a single method (which sounds awful):
e0.ifExist(Element::actionAAndC);
The lambda now is even less 'readable' then the if was.
e0.ifExist(e -> {
e0.actionA();
e0.actionC();
});
But how much effort would we make to do that? And how much effort will we put into maintaining it all?
if(e0.exist()) {
e0.actionA();
e0.actionC();
}
If you are performing a simple check on an object and then executing some statements based on the condition then one approach would be to have a Map with a Predicate as key and desired expression as value
for example.
Map<Predicate<Integer>,Supplier<String>> ruleMap = new LinkedHashMap <Predicate<Integer>,Supplier<String>>(){{
put((i)-> i<10,()->"Less than 10!");
put((i)-> i<100,()->"Less than 100!");
put((i)-> i<1000,()->"Less than 1000!");
}};
We could later stream the following Map to get the value when the Predicate returns true which could replace all the if/else code
ruleMap.keySet()
.stream()
.filter((keyCondition)->keyCondition.test(numItems,version))
.findFirst()
.ifPresent((e)-> System.out.print(ruleMap.get(e).get()));
Since we are using findFirst() it is equivalent to if/else if /else if ......
I have this simple fragment that I would like to reengineer in a more elegant way maybe with the latest JDK 8 features:
String x = methodCall();
if(x==null) {x=method2();}
if(x==null) {x=method3();}
if(x==null) {x=method4();}
// doing calculation with X
You can use Streams:
Optional<String> result= Stream.<Supplier<String>>of(this::method1, this::method2, this::method3)
.map(Supplier::get)
.filter(Objects::nonNull)
.findFirst();
System.out.println(result.isPresent());
The above code is equal to this (generated with Intellij Idea)
Optional<String> result = Optional.empty();
for (Supplier<String> stringSupplier : Arrays.<Supplier<String>>asList(this::method1, this::method2, this::method3)) {
String s = stringSupplier.get();
if (s != null) {
result = Optional.of(s);
break;
}
}
The question explicitly mentions Java 8, but also mentions the "latest features". As it isn't clear which the OP wants, this answer is with the latest features.
With Java 9 you can use the new Optional.or method to concisely implement this logic:
import static java.util.Optional.ofNullable;
...
String x = ofNullable(methodCall())
.or(() -> ofNullable(method2()))
.or(() -> ofNullable(method3()))
.or(() -> ofNullable(method4()))
.orElse(null);
Depending on what you are doing, you might want to omit the .orElse(null).
You can get rid of the if-block by using a designated method but besides that you won't get it more compact. Especially you will still need to check for null after each method.
Here is a method which uses Optional#ifPresent to apply a method if its not present:
public <V> void runIfNotPresent(V value, Runnable method) {
if (value == null) {
method.run();
}
}
Here's your code with using that method:
x = methodCall();
runIfNotPresent(x, this::method2);
runIfNotPresent(x, this::method3);
runIfNotPresent(x, this::method4);
// doing calculation with X
Note that you can't directly use Optional#isPresent (documentation) as its logic would be reversed. However that is also a very useful class and if you're using Java 9 then you might want to use Optional#or (documentation) as others already showed in their answers.
Alternatively you could write your own method to chain-apply methods
public <V> V applyAsLongAsNull(V value, Function<V, V>... methods) {
// Apply methods
for (Function<V, V> method : methods) {
if (value == null) {
value = method.apply(value);
} else {
// Stop as soon as value is not null
break;
}
}
return value;
}
You could then transform your methodX to a Function<V, V> which accepts a String value and returns a possibly different String value:
public String methodX(String value) {
// Do something with value
...
// Return value
return value;
}
Finally you would use it like:
String x = methodCall();
x = applyAsLongAsNull(x, this::method2, this::method3, this::method4);
// doing calculation with X
I want my mock to return method1() when called 10 times and return method2() when called after that. The code below works with an anonymous inner class. Is there an elegant way to do this in Java 8?
when(mock.doSomething()).thenAnswer(
new Answer<Account>() {
private int count = 0;
#Override
public Account answer(InvocationOnMock invocationOnMock) throws Throwable {
if (count < 10) {
count++;
return method1();
}
return method2();
}
}
);
Since mutable state like a counter and Java 8’s lambda expressions do not work well together, there is no straight-forward, Java 8 specific solution with a counter. And every attempt to find a clever work-around will be worse than the following, counter-free solution
public static <T> OngoingStubbing<T> switchAfter(
OngoingStubbing<T> stub, int calls, Supplier<T> first, Supplier<T> then) {
Answer<T> a1=x -> first.get(), a2=x -> then.get();
while(calls-->0) stub=stub.then(a1);
return stub.then(a2);
}
which is just the equivalent of using
Mockito.when(mock.doSomething()).then(x -> method1()).then(x -> method1())
.then(x -> method1()).then(x -> method1()).then(x -> method1()).then(x -> method1())
.then(x -> method1()).then(x -> method1()).then(x -> method1()).then(x -> method1())
.then(x -> method2());
Usable as
switchAfter(Mockito.when(mock.doSomething()), 10, () -> method1(), () -> method2());
Thinking about it again, there is a solution which is not simpler in terms of code, but preferable if the count of first calls is large:
public static <T> Answer<T> switchAfter(int calls, Supplier<T> first, Supplier<T> then) {
Iterator<T> it=Stream.concat(
IntStream.range(0, calls).mapToObj(i -> first.get()),
Stream.generate(then))
.iterator();
return x -> it.next();
}
usable as
Mockito.when(mock.doSomething()).then(switchAfter(10, () -> method1(), () -> method2()));
Answer is a single-method interface so you may be able to simplify the anonymous inner class boilerplate. I don't think there's any built-in alternative to simplify your logic unless you were to extract it to a method you write (like firstNTimes(invocation -> method1(), 10, invocation -> method2())).
when(mock.doSomething()).thenAnswer(invocationOnMock -> {
if (count < 10) {
count++;
return method1();
}
return method2();
});
I didn't get a chance to test this; if the Throwable or Answer generics cause you any trouble, please comment and I'll take another look.
How can I express this with java8 streaming-API?
I want to perform itemConsumer for every item of a stream. If there
are no items I want to perform emptyAction.
Of course I could write something like this:
Consumer<Object> itemConsumer = System.out::println;
Runnable emptyAction = () -> {System.out.println("no elements");};
Stream<Object> stream = Stream.of("a","b"); // or Stream.empty()
List<Object> list = stream.collect(Collectors.toList());
if (list.isEmpty())
emptyAction.run();
else
list.stream().forEach(itemConsumer);
But I would prefer to avoid any Lists.
I also thought about setting a flag in a peek method - but that flag would be non-final and therefore not allowed. Using a boolean container also seems to be too much of a workaround.
You could coerce reduce to do this. The logic would be to reduce on false, setting the value to true if any useful data is encountered.
The the result of the reduce is then false then no items have been encountered. If any items were encountered then the result would be true:
boolean hasItems = stream.reduce(false, (o, i) -> {
itemConsumer.accept(i);
return true;
}, (l, r) -> l | r);
if (!hasItems) {
emptyAction.run();
}
This should work fine for parallel streams, as any stream encountering an item would set the value to true.
I'm not sure, however, that I like this as it's a slightly obtuse use of the reduce operation.
An alternative would be to use AtomicBoolean as a mutable boolean container:
final AtomicBoolean hasItems = new AtomicBoolean(false);
stream.forEach(i -> {
itemConsumer.accept(i);
hasItems.set(true);
});
if (!hasItems.get()) {
emptyAction.run();
}
I don't know if I like that more or less however.
Finally, you could have your itemConsumer remember state:
class ItemConsumer implements Consumer<Object> {
private volatile boolean hasConsumedAny;
#Override
public void accept(Object o) {
hasConsumedAny = true;
//magic magic
}
public boolean isHasConsumedAny() {
return hasConsumedAny;
}
}
final ItemConsumer itemConsumer = new ItemConsumer();
stream.forEach(itemConsumer::accept);
if (!itemConsumer.isHasConsumedAny()) {
emptyAction.run();
}
This seems a bit neater, but might not be practical. So maybe a decorator pattern -
class ItemConsumer<T> implements Consumer<T> {
private volatile boolean hasConsumedAny;
private final Consumer<T> delegate;
ItemConsumer(final Consumer<T> delegate) {
this.delegate = delegate;
}
#Override
public void accept(T t) {
hasConsumedAny = true;
delegate.accept(t);
}
public boolean isHasConsumedAny() {
return hasConsumedAny;
}
}
final ItemConsumer<Object> consumer = new ItemConsumer<Object>(() -> /** magic **/);
TL;DR: something has to remember whether you encountered anything during the consumption of the Stream, be it:
the Stream itself in case of reduce;
AtomicBoolean; or
the consumer
I think the consumer is probably best placed, from a logic point of view.
A solution without any additional variables:
stream.peek(itemConsumer).reduce((a, b) -> a).orElseGet(() -> {
emptyAction.run();
return null;
});
Note that if the stream is parallel, then itemConsumer could be called simultaneously for different elements in different threads (like in forEach, not in forEachOrdered). Also this solution will fail if the first stream element is null.
There’s a simple straight-forward solution:
Spliterator<Object> sp=stream.spliterator();
if(!sp.tryAdvance(itemConsumer))
emptyAction.run();
else
sp.forEachRemaining(itemConsumer);
You can even keep parallel support for the elements after the first, if you wish:
Spliterator<Object> sp=stream.parallel().spliterator();
if(!sp.tryAdvance(itemConsumer))
emptyAction.run();
else
StreamSupport.stream(sp, true).forEach(itemConsumer);
In my opinion, it is much easier to understand as a reduce based solution.
You could do this:
if(stream.peek(itemConsumer).count() == 0){
emptyAction.run();
}
But it seems that count may be changed to skip the peek if it knows the size of the Stream in Java 9 (see here), so if you want it to work in the future you could use:
if(stream.peek(itemConsumer).mapToLong(e -> 1).sum() == 0){
emptyAction.run();
}
Another attempt to use reduce:
Stream<Object> stream = Stream.of("a","b","c");
//Stream<Object> stream = Stream.empty();
Runnable defaultRunnable = () -> System.out.println("empty Stream");
Consumer<Object> printConsumer = System.out::println;
Runnable runnable = stream.map(x -> toRunnable(x, printConsumer)).reduce((a, b) -> () -> {
a.run();
b.run();
}).orElse(defaultRunnable);
runnable.run(); // prints a, b, c (or empty stream when it is empty)
// for type inference
static <T> Runnable toRunnable(T t, Consumer<T> cons){
return ()->cons.accept(t);
}
This approach does not use peek() which according to Javadoc "mainly exists to support debugging"