Interference between onErrorResume() and thenReturn() - java

I cannot understand how Flux.onErrorContinue() works. Based on Does Reactor onErrorContinue operator let the original sequence continue? I created a similar example to understand it better, but I am lost.
Especially weird is the interference between onErrorContinue() and thenReturn().
I have the following code:
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
class OnErrorContinueTest {
#Test
void testOnErrorContinue() {
Flux.range(1, 3)
.doOnNext(n -> System.out.println("Main-1: " + n))
.flatMap(this::processElement)
.doOnNext(n -> System.out.println("Main-2: " + n)) // Why does onErrorContinue recovers that line, if it is after?
.onErrorContinue((ex, o) -> System.err.println(" Error processing " + o + " - " + ex.getMessage()))
.doOnNext(n -> System.out.println("Main-3: " + n))
.subscribe();
}
#Test
void testOnErrorResume() {
Flux.range(1, 3)
.doOnNext(n -> System.out.println("Main-1: " + n))
.flatMap(n -> this.processElement(n)
.doOnError(ex -> System.err.println(" Error processing " + n + " - " + ex.getMessage()))
.onErrorResume(e -> Mono.empty()))
.doOnNext(n -> System.out.println("Main-2: " + n))
.subscribe();
}
Mono<Integer> processElement(Integer i) {
return Mono.just(i)
.doOnNext(n -> System.out.println(" Process-1: " + n))
.doOnNext(n -> {
if (n == 2) {
throw new RuntimeException("Forcing exception for " + n);
}
})
.doOnNext(n -> System.out.println(" Process-2: " + n))
.thenReturn(i) // Why does onErrorContinue recovers everything after that line?
.doOnNext(n -> System.out.println(" Process-3: " + n))
;
}
}
testOnErrorResume() produces exactly what I would expect:
Main-1: 1
Process-1: 1
Process-2: 1
Process-3: 1
Main-2: 1
Main-1: 2
Process-1: 2
Error while processing 2 - Forcing exception for 2
Main-1: 3
Process-1: 3
Process-2: 3
Process-3: 3
Main-2: 3
However, testOnErrorContinue() produces:
Main-1: 1
Process-1: 1
Process-2: 1
Process-3: 1
Main-2: 1
Main-3: 1
Main-1: 2
Process-1: 2
Error while processing 2 - Forcing exception for 2
Process-3: 2 -- UNEXPECTED - WHY IS THIS PRINTED?
Main-2: 2 -- UNEXPECTED - WHY IS THIS PRINTED?
Main-3: 2
Main-1: 3
Process-1: 3
Process-2: 3
Process-3: 3
Main-2: 3
Main-3: 3
My doubts:
Why does onErrorContinue() recover inside the processElement() method? It seems like thenReturn() has something to do with it, but cannot understand how, because the thenReturn()s documentation states
On an error in the original Mono, the error signal is propagated instead.
Why does onErrorContinue() recover before it is called? Why is the code System.out.println("Main-2: " + n) executed?

Related

String return value in recursive function in java

So I'm practicing java currently, I'm a beginner and I try to explain all the examples that I code so I can understand how and why things are like that. I understand the concept of recursion but I came across this problem when I tried to explain this code:
import java.util.Scanner;
public class JavaExample {
public static void main(String[] args) {
String str;
System.out.println("Enter your username: ");
Scanner scanner = new Scanner(System.in);
str = scanner.nextLine();
scanner.close();
String reversed = reverseString(str);
System.out.println("The reversed string is: " + reversed);
}
public static String reverseString(String str)
{
if (str.isEmpty())
return str;
//Calling Function Recursively
return reverseString(str.substring(1)) + str.charAt(0);
}
}
With my knowledge so far about recursion, I tried to explain it like this.
Let's have for example a string "Petar":
reverseString(etar)+P
reverseString((tar)+etar)+P
reverseString((ar)+tar+etar)+P
reverseString((r)+ar+tar+etar)+P
-----------------------------------
r+ar+tar+etar+P
I noticed that the right answer is the first character from every individual piece, so I must be close.
Thank you for your time and I'm sorry if I didn't express myself clearly, I'm from Europe (sry bad inglish).
You doing good for first line reverseString(etar)+P you keep at the end only the *first char**, just do the same for next lines
put first char at the end
send the rest to the method
reverseString(etar)+P
reverseString(tar) +e+P
reverseString(ar) +t+e+P
reverseString(r) +a+t+e+P
reverseString('') +r+a+t+e+P // stops when empty string is passed
You got the first call right but the others were a bit off. In each recursive call you return the the string with the first character at the end instead of the begining. Thus, the recursion looks something like this:
reverseString("Petar")
return reverseString("etar") + "P"
return reverseString("tar") + "e"
return reverseString("ar") + "t"
return reverseString("r") + "a"
return reverseString("") + "r"
return ""
So the function will return: (((((("")+"r")+"a")+"t")+"e")+"P"), which is "rateP".
It should become clear when start with the simplest possible example: the empty string and string of size 1. Then substituting arguments of each call, to make it more obvious:
// string.isEmpty() is true, so the empty string is returned immediately
reverse("") -> ""
reverse("a") -> reverse("") + 'a' -> ("") + 'a' -> "a"
These are the trivial examples, let's try it with longer strings:
reverse("ab") -> reverse("b") + 'a'
reverse("abc") -> reverse("bc") + 'a'
-> (reverse("c") + 'b') + 'a'
-> ((reverse("") + 'c') + 'b') + 'a'
-> ((("") + 'c') + 'b') + 'a'
-> "cba"
The general pattern should be clear now. For the sake of completeness, let's manually "unroll" the recursive calls for a 4 character string:
reverse("abcd") -> reverse("bcd") + 'a'
-> (reverse("cd") + 'b') + 'a'
-> ((reverse("d") + 'c') + 'b') + 'a'
-> (((reverse("") + 'd') + 'c') + 'b') + 'a'
-> (((("") + 'd') + 'c') + 'b') + 'a'
-> "dcba"
It works like this:
reverseString("Peter") =
reverseString("eter") + P =
(reverseString("ter") + e) + P =
((reverseString("er") + t) + e) + P =
(((reverseString("r") + e) + t) + e) + P =
((((reverseString("") + r) + e) + t) + e) + P =
(((("" + r) + e) + t) + e) + P =
((((r) + e) + t) + e) + P =
(((r + e) + t) + e) + P =
(((re) + t) + e) + P =
((re + t) + e) + P =
((ret) + e) + P =
(ret + e) + P =
(rete) + P =
rete + P =
reteP
On your example when your function reaches only one character like
Peter when it becomes only "P"
and the string is not empty you call
substring(1)
Which calls an index out of the range while the string only have P on index 0 and none on index 1
You have to put a base case that checks if the string length is equal to 1 or less

Cloud you help me to describe How recursive program thinking ? (step by step)

As I study recursive algorithms that code below:
String n = starString(3);
System.out.print(n);
} public static String starString(int n){
if(n < 0) {
throw new IllegalArgumentException();
}else if(n == 0) {
return "*";
}else{
return starString(n - 1) + starString(n - 1);
}
I think code will working look like below
String n = starString(3); //Value is 3 then send 3 to function
so it goes to the else condition 3 times, right?
starString(3 - 1) + starString(3 - 1); //Its return is "**"
starString(2 - 1) + starString(2 - 1); //Its return is "**"
starString(1 - 1) + starString(1 - 1); //Its return is "**"
I think that the result should look like this --> ****** //6 items
but the program shows the following instead --> ******** //8 items
Can someone clarify why this is?
When you call starString(3), it returns:
starString(2) + starString(2)
The above expression expands to become (this is where you got it wrong):
(starString(1) + starString(1)) + (starString(1) + starString(1))
Then each of those calls expand to become:
((starString(0) + starString(0)) + (starString(0) + starString(0))) + ((starString(0) + starString(0)) + (starString(0) + starString(0)))
Here's a formatted version of the above:
(
(starString(0) + starString(0))
+
(starString(0) + starString(0))
)
+
(
(starString(0) + starString(0))
+
(starString(0) + starString(0))
)
The outer most bracket is the starString(2) call. The inner bracket is the starString(1) call.
As you can see, there are 8 calls to starString, so 8 *s.

function of == in println()

String literal1 = "java";
String object = new String("java");
String literal2 = "java";
System.out.println("result 1 = " + (literal1 == object) );
System.out.println("result 2 = " + literal1.equals(object));
System.out.println("result 3 = " + literal1 == object);
System.out.println("result 4 = " + literal1.equals(object));
System.out.println("result 5 = " + literal1 == literal2);
System.out.println("result 6 = " + literal1.equals(literal2));
Expected output
result 1 = false
result 2 = true
result 3 = false
result 4 = true
result 5 = false
result 6 = true
output obtained
result 1 = false
result 2 = true
false
result 4 = true
false
result 6 = true
When this line
System.out.println("result 5 = " + literal1 == literal2);
is changed to
System.out.println("result 5 = " + (literal1 == literal2));
Output
result 5 = true
Could anyone please explain why this is happening?
It happens because expressions are evaluated left-to-right so it will first concatenate your string (i.e. "result 3 = " + literal1) and then check for truthiness (i.e. == object), hence printing only false because the result of the concatenation is not of the same value as object.
In the first (and last) example ("result 1 = " + (literal1 == object)) you direct the default evaluation with brackets forcing (literal == object) to evaluate separately before the concatenation which is why it prints false only for that evaluation, concatenated with the string preceding it.
TLDR: it's precedence, not left-to-right
Java does have a rule that operands are evaluated left-to-right, but that has no effect here.
Also in Java all binary (meaning two-operand, not bitwise) operators other than assignment are left-associative, but that does not apply here because associativity only matters when operators have the same precedence.
What matters here is that + has higher precedence than == so as VietDD says
System.out.println("result 5 = " + literal1 == literal2);
# is equivalent to
System.out.println(("result 5 = " + literal1) == literal2);
# which is false because they aren't the same object
which happens to be the same as grouping to the left.
But if we consider instead
System.out.println(literal1 == literal2 + " is result 5!");
# THAT is equivalent to
System.out.println(literal1 == (literal2 + " is result 5!"));
# ditto
which happens to be the same as grouping to the right.
System.out.println("result 3 = " + literal1 == object);
System.out.println("result 5 = " + literal1 == literal2);
is equivalent to
System.out.println( ( "result 3 = " + literal1 ) == object);
System.out.println( ( "result 5 = " + literal1 ) == literal2);
It's String Concatenation
The expression is evaluated left to right.
If either operand is a String, + means concatenation
You can try this :
System.out.println( 1 + 2 + "3");
Output :
33
1 + 2 = 3
3 + "3" = "33"
And
System.out.println( "1" + 2 + 3);
Output:
123
"1" + 2 = "12"
"12" + 3 = "123

java8 changing from imperative to functional

following is my the imperative style of code
for (int i = 1; i <= sundayOpenAreas.size(); i++) {
String area = sundayOpenAreas.get(i - 1);
String postcode = "XX" + i + " 1AA";
boolean sundayDeliveryAvailable = sundayDeliveryAvailable(area, postcode);
Assert.assertTrue(sundayDeliveryAvailable, area + " should accept deliveries on Sunday to " + postcode + "!");
System.out.println(area + ", " + postcode);
}
would like to convert to functional style java8 streams , and following is what tried so far
IntStream.range(0, sundayOpenAreas.size())
.forEach(
idx -> {
sundayOpenAreas.stream()
.map(x -> "XX" + idx + "".concat("1AA"))
//Struck here on how to proceed
//System.out.println(abc);
});
where sundayOpenAreas is List<String>
First I think you should stick to your imperative approach, because you need multiple variables in the pipeline.
I would give this a try:
IntStream.range(0, sundayOpenAreas.size())
.mapToObj(i -> new String[] { sundayOpenAreas.get(i), "XX" + i + " 1AA" })
.peek(s -> Assert.assertTrue(sundayDeliveryAvailable(s[0], s[1]),
s[0] + " should accept deliveries on Sunday to " + s[1] + "!"))
.forEachOrdered(s -> System.out.println(s[0] + ", " + s[1]));
Try this:
IntStream.range(0, sundayOpenAreas.size())
.forEach(idx -> {
sundayOpenAreas.stream()
.map(x -> "XX" + idx + "".concat("1AA"))
.filter(x -> sundayDeliveryAvailable(sundayOpenAreas.get(idx), x)).forEach(System.out::println);
});
Here is the code which you can try:
IntStream.of(sundayOpenAreas.size())
.filter(i -> {
String postcode = "XX" + i + " 1AA";
return sundayDeliveryAvailable(String.valueOf(i), postcode);
})
.forEach(System.out::println);

why integer is added with string in System.out.println ? in java

String s = new String("5");
System.out.println(1 + 10 + s + 10 + 5);
output of the following function is 115105 how ?
"+" is left associative so
1 + 10 => 11(int)
11 + s => "115"(String)
"115" + 10 => "11510"(String) 10 is converted to String
"11510" + 5 = "115105"(String) 5 is converted to String
Your code effectively functions as integer summation as long as it's possible, because the evaluation process goes from left to right. Once the String is encountered, the function switches to concatenation.
1 + 10 + "5" + 10 + 5
= (1 + 10) + "5" + 10 + 5
= 11 + "5" + 10 + 5
= 115105
String s = new String("5");
System.out.println(1 + 10 + s + 10 + 5);
Since expressions are evaluated from left to rignt your code is same as
System.out.println((((1 + 10) + "5") + 10) + 5);
So first (1 + 10) is evaluated and since it is simple integer addition you are getting 11 so your code becomes
System.out.println(((11 + "5") + 10) + 5);
Now (11 + "5") is evaluated and since one of arguments is String, it is being concatenated and result will also be String. So 11 + "5" becomes "11"+"5" which gives us String "115".
So after that our code is same as
System.out.println(("115" + 10) + 5);
and again in ("115" + 10) one of arguments is String so we are getting "115"+"10" which gives us another String "11510".
So finally we are getting to the point where we have
System.out.println("11510" + 5);
which is same as
System.out.println("115105");
(1 + 10)and 10 and 5 are regarded as three strings in your code
Java casts the integers as a string when you include a string in the addition, it becomes concatenation. Try
import java.io.*;
import java.util.*;
import java.lang.*;
public class mainactivity {
public static void main(String a[]) {
String s = new String("5");
System.out.println((1 + 10) + s + (10 + 5));
}
}
This should output 11515.

Categories