How Consumer andThen method works internally in java functional interfaces - java

can someone let me know how the below program works internally:
public class Main {
public static void main(String[] args) {
Consumer<String> c = (x) -> System.out.println(x.toLowerCase());
c.andThen(c).andThen(c).accept("Java2s.com");
}
}

Did you look at the code of andThen?
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
It's creating a new Consumer for each call to andThen, finally at the end invoking the accept method (which is the only abstract one).
How about a different approach:
Consumer<String> first = x -> System.out.println(x.toLowerCase());
Consumer<String> second = y -> System.out.println("aaa " + y);
Consumer<String> result = first.andThen(second);
Running this code is not going to produce anything, since you have not invoked accept anywhere just yet.
On the other hand, you can see what happens when calling accept on each other:
Consumer<String> result = first.andThen(second);
first.accept("Java"); // java
second.accept("Java"); // aaa Java
System.out.println("---------");
result.accept("Java"); // java, aaa Java
andThen returns a composition of this Consumer with the next one.

the documentation Consumer#andThen says:
Returns a composed Consumer that performs, in sequence, this operation followed by the after operation. If performing either operation throws an exception, it is relayed to the caller of the composed operation. If performing this operation throws an exception, the after operation will not be performed.
which means your consumer will be accepted 3 times, like as:
v--- 1. c.accept("Java2s.com");
c.andThen(c).andThen(c).accept("Java2s.com");
^ ^
| |
| 3. c.accept("Java2s.com");
|
2. c.accept("Java2s.com");

Related

Why does the following lambda compile when assigning it to Runnable? [duplicate]

This question already has answers here:
Why does this Java 8 lambda fail to compile?
(4 answers)
Lambda Expression that has return type as void can compile with wrapper but not compile with primitive [duplicate]
(2 answers)
Valid void Return Statements from Lambda Expressions (Example: Runnable)
(3 answers)
Why Java 8 Stream forEach method behaves differently?
(4 answers)
Closed last month.
I have the following piece of code which obviously can not be compiled:
jshell> static int counter = 0;
counter ==> 0
jshell> Runnable r = () -> counter;
| Error:
| incompatible types: lambda body is not compatible with a void functional interface
| (consider using a block lambda body, or use a statement expression instead)
| Runnable r = () -> counter;
|
This is understandable, since the signature for the Runnable's run is void run(). Now, if I have the following lambda, this will compile just fine:
jshell> static int counter = 0;
counter ==> 0
jshell> Runnable r = () -> counter++;
r ==> $Lambda$23/0x0000000800c0b260#3941a79c
Why does this piece of code compile, knowing that counter++ will still return an integer?
Also, what makes it more confusing is that this code can also be compiled:
jshell> Supplier<Integer> f = () -> counter++;
f ==> $Lambda$22/0x0000000800c0a410#12edcd21
I tried compiling the code above using Java 17's jshell.
In the Runnable, the returned value is ignored; the main part (why it compiles) is that there is a statement in it.
It does return a value, so it's also a Supplier. It also manipulates counter (as a side effect), but that doesn't matter for fulfilling the functional interface. .
(Expanding the comment, piggybacking on other answer and comment)
The error message itself provides some guidance if you interpret consider using a block lambda body as "consider what would happen if you used a block lambda body".
When you write a block-less lambda function arguments -> something, Java will still pick one from two actual blocks:
void somefunction(arguments) {
something;
}
and (as other answer and comment point out) in this case something; has to be a valid statement
sometype somefunction(arguments) {
return something;
}
where something has to be a valid expression, providing a result to return.
The choice is explicit, you personally do it when specifying the type of the lambda itself.
So when you write Runnable, which has a single void run() method, Java tries to create it for you:
void run() {
counter;
}
this won't work because counter; doesn't exist in Java
void run() {
return counter;
}
this won't work because a void method can't return a number.
However this latter one would work with Supplier<Integer> which has a single Integer get() method:
Integer get() {
return counter;
}
this method can exist (with the automatic int->Integer boxing).
And when you have counter++, both can exist, (1.) for Runnable and (2.) for Supplier<Integer>:
class InnerClassForLambda implements Runnable {
public void run() {
counter++;
}
}
increments counter and doesn't return anything
class InnerClassForLambda implements Supplier<Integer> {
Integer get() {
return counter++;
}
}
increments counter and returns what it was before the increment.
Compare
jshell> Runnable r = () -> counter++;
with
jshell> Runnable r = () -> System.out.println("Hello");
and then it makes it easier to understand why the former compiles.
Like System.out.println("Hello");, counter++; is also a statement.
Now,
Supplier<Integer> f = () -> counter++;
compiles because counter++ does return a value.

Difference in Mono.fromCallable And Mono.justOrEmpty

What is the different between the following two executions?
Mono.justOrEmpty(someFunction())
.doOnNext(() -> doSomeTask()).subscribe();
Mono.fromCallable(() -> someFunction())
.doOnNext(() -> doSomeTask()).subscribe();
With Mono.fromCallable, the Callable is called lazily only when the resulting Mono is subscribed to.
(you can even rewrite your snippet to Mono.fromCallable(this::someFunction) if someFunction doesn't take any parameter)
With Mono.justOrEmpty, the value is captured immediately by the operator for future emission. So in effect here the someFunction() method is called immediately at construction.
Note that both of these variants will correctly deal with someFunction() returning null (unlike Mono.just(...)). In that case, the resulting Mono will simply complete (onComplete signal without onNext).
Note also that if the method is blocking and long running, it might be an antipattern in both cases. See https://projectreactor.io/docs/core/release/reference/#faq.wrap-blocking
Basically using Mono.fromCallable() Callable emits the resulting value as Mono. Mono.justOrEmpty() only emits the specified item as Mono if it exists.
In the official docs justOrEmpty and fromCallable are described as follows:
Mono.justOrEmpty()
Create a new Mono that emits the specified item if non null otherwise only emits onComplete.
Mono.fromCallable()
Create a Mono producing its value using the provided Callable. If the Callable resolves to null, the resulting Mono completes empty.
If you need more detailed information about Mono, you can check the official documentation.
With Mono.fromCallable, someFunction will be called when a subscription is made.
private static Integer someFunction() {
System.out.println("calling someFunction");
return 1;
}
public static void main(String[] args) {
Mono<Integer> mono = Mono.fromCallable(ReactorApp2::someFunction)
.doOnNext(System.out::println);
System.out.println("Subscribing...");
mono.subscribe();
mono.subscribe();
}
/*
Subscribing...
calling someFunction
1
calling someFunction
1
*/
With Mono.justOrEmpty, someFunction will be called only once.
private static Integer someFunction() {
System.out.println("calling someFunction");
return 1;
}
public static void main(String[] args) {
Mono<Integer> mono = Mono.justOrEmpty(someFunction())
.doOnNext(System.out::println);
System.out.println("Subscribing...");
mono.subscribe();
mono.subscribe();
}
/*
calling someFunction
Subscribing...
1
1
*/

Java annotation to mark a function argument should be thread-safe

Let's say I have a function signature as follows -
class CustomerStore {
public void processCustomerInfo(final BiConsumer<Integer, CustomerInfo.V> consumer) throws Exception
}
consumer is executed in parallel threads inside processCustomerInfo.
Can someone let me know is there any annotation we should be adding to denote that passed in consumer should be threadsafe (other than comments)?
For example, the below caller code is not quite correct.
final Map<Integer, CustomerInfo.V> cust = new HashMap<>(); // Should be ConcurrentHashMap
fdbCustomerStore.processCustomerInfo((cid, v) -> cust.put(cid, v));

What is Futures.transform() lambda argument in case the original ApiFuture / ListenableFuture failed or cancelled

I have a method that sends asynchronously a list of messages. Each send returns ApiFuture<String> (GCP version of Guava's ListenableFuture). I need this method to return one Future<Boolean>, so I
Create a list dependency on each ApiFuture<String>
Transform the resulting ApiFuture<List<String>> to a Future<Boolean> using ApiFutures.transform method
ApiFuture< List < String > > allSentFuture = ApiFutures.allAsList(futures);
return ApiFutures.transform(allSentFuture, val -> {
return true;
},
Executors.newCachedThreadPool()
);
My question is: what is the value of val argument of the lambda above if one or more of the original futures are failed/cancelled? Is the lambda even called in this case?
Thanks!
ApiFuture<V> forms a monad over the type V, and transform applies a function to the encapsulated value of type V. If the ApiFuture<V> does not contain a V value because it is failed or cancelled, then the transformed future is the same.
If you want to handle failures due to exceptions, you can use ApiFutures.catching() to produce an alternative result (e.g. Boolean.FALSE) instead.
If you want to transform cancellation into a successful value, I believe you would need to use ApiFuture.addListener directly, and have the listener complete a SettableApiFuture which you return. Then the listener (which will get called when the source future is cancelled) can check isCancelled to detect this case, or can catch and handle the CancellationException.
For example:
/**
* Adapt an iterable of {#link ApiFuture} instances into a single {#code ApiFuture}.
*/
static <T> ApiFuture<Boolean> adaptFutures(Iterable<ApiFuture<T>> futures) {
final SettableApiFuture<Boolean> result = SettableApiFuture.create();
final ApiFuture<List<T>> allFutures = ApiFutures.allAsList(futures);
allFutures.addListener(
() -> {
if (allFutures.isCancelled()) {
result.set(Boolean.FALSE);
return;
}
try {
allFutures.get();
result.set(Boolean.TRUE);
} catch (ExecutionException | InterruptedException ex) {
// Maybe log something here?
//
// Note that InterruptedException is actually impossible here
// because we're running in the listener callback, but the API
// still marks it as potentially thrown by .get() above.
//
// So if we reach here it means that the allAsList future failed.
result.set(Boolean.FALSE);
}
},
// Not normally safe, but we know our listener runs fast enough
// to run inline on the thread that completes the last future.
Runnable::run);
return result;
}

Chain CompletableFuture and stop on first success

I'm consuming an API that returns CompletableFutures for querying devices (similar to digitalpetri modbus).
I need to call this API with a couple of options to query a device and figure out what it is - this is basically trial and error until it succeeds. These are embedded device protocols that I cannot change, but you can think of the process as working similar to the following:
Are you an apple?
If not, then are you a pineapple?
If not, then are you a pen?
...
While the API uses futures, in reality, the communications are serial (going over the same physical piece of wire), so they will never be executed synchronously. Once I know what it is, I want to be able to stop trying and let the caller know what it is.
I already know that I can get the result of only one of the futures with any (see below), but that may result in additional attempts that should be avoided.
Is there a pattern for chaining futures where you stop once one of them succeeds?
Similar, but is wasteful of very limited resources.
List<CompletableFuture<String>> futures = Arrays.asList(
CompletableFuture.supplyAsync(() -> "attempt 1"),
CompletableFuture.supplyAsync(() -> "attempt 2"),
CompletableFuture.supplyAsync(() -> "attempt 3"));
CompletableFuture<String>[] futuresArray = (CompletableFuture<String>[]) futures.toArray();
CompletableFuture<Object> c = CompletableFuture.anyOf(futuresArray);
Suppose that you have a method that is "pseudo-asynchronous" as you describe, i.e. it has an asynchronous API but requires some locking to perform:
private final static Object lock = new Object();
private static CompletableFuture<Boolean> pseudoAsyncCall(int input) {
return CompletableFuture.supplyAsync(() -> {
synchronized (lock) {
System.out.println("Executing for " + input);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return input > 3;
}
});
}
And a List<Integer> of inputs that you want to check against this method, you can check each of them in sequence with recursive composition:
public static CompletableFuture<Integer> findMatch(List<Integer> inputs) {
return findMatch(inputs, 0);
}
private static CompletableFuture<Integer> findMatch(List<Integer> inputs, int startIndex) {
if (startIndex >= inputs.size()) {
// no match found -- an exception could be thrown here if preferred
return CompletableFuture.completedFuture(null);
}
return pseudoAsyncCall(inputs.get(startIndex))
.thenCompose(result -> {
if (result) {
return CompletableFuture.completedFuture(inputs.get(startIndex));
} else {
return findMatch(inputs, startIndex + 1);
}
});
}
This would be used like this:
public static void main(String[] args) {
List<Integer> inputs = Arrays.asList(0, 1, 2, 3, 4, 5);
CompletableFuture<Integer> matching = findMatch(inputs);
System.out.println("Found match: " + matching.join());
}
Output:
Executing for 0
Executing for 1
Executing for 2
Executing for 3
Executing for 4
Found match: 4
As you can see, it is not called for input 5, while your API (findMatch()) remains asynchronous.
I think the best you can do is, after your retrieval of the result,
futures.forEach(f -> f.cancel(true));
This will not affect the one having produced the result, and tries its best to stop the others. Since IIUC you get them from an outside source, there's no guarantee it will actually interrupt their work.
However, since
this class has no direct control over the computation that causes it to be completed, cancellation is treated as just another form of exceptional completion
(from CompletableFuture doc), I doubt it will do what you actually want.

Categories

Resources