Java Recursive function trick - java

Could anyone explain the output of this program? Why is the is the second value 7?
Not able to understand recursive function call go(this)
public class ThisIsTricky {
int state = 0;
public ThisIsTricky(int s) {
state = s;
}
public static void main(String[] args) {
ThisIsTricky obj1 = new ThisIsTricky(1);
ThisIsTricky obj2 = new ThisIsTricky(2);
System.out.println(obj1.go(obj1) + "" + obj2.go(obj2));
}
int go(ThisIsTricky thisIsTricky) {
if (this.state == 2) {
thisIsTricky.state = 5;
go(this);
}
return ++this.state;
}
}
Output:-
2 7

The important thing to notice is that state is a member variable, so it is not shared between obj1 and obj2. Each has its own value (1 and 2, respectively).
Why is the output 7 for obj2? The condition (this.state == 2) is true for obj2, so you go recursively into go(this). Now the condition is not true anymore because state was changed to 5, so state gets incremented. Recursive call ends and you now return to the calling function (after go(this)) and state gets incremented again. Therefore, 5+1+1 = 7.

'obj1': 'state=1' and '1!=2' so return 1+1= 2.
'obj2' Is easier to understand when you unravel the recursion:
State = 2 so we enter the conditional clause:
Set state=5
Recursively call to 'go'
state is 5 and 5!=2. So skip conditional clause
increment state, state is now 5+1=6
return 6
Back in the original call to 'go', increment state, state is now 6+1=7
return 7
Thus, the output is 27

The output of the program would come out to be 27 ( without spaces ). This is due to java passing the address of the object variables in the function calls.
The first 2 would be the result of the call of obj1.go(obj1) which would be an increment in the state value of obj1.
The next output would be 7 when obj2.go(obj2) is called and as the obj2's state value being 2 triggers the if statement and changes the state value to 5.Then the recursive function go(this) is called again with the same address of original parameter. This time the if statement is not called and the function simply returns an incremented value , that is 6. The control then returns to the original function and the function returns an increment to that value , that is 7 and it is printed in the output.

Related

How to mock the function in a loop using Mockito in Java to return different value for each iteration [duplicate]

This question already has answers here:
How to tell a Mockito mock object to return something different the next time it is called?
(5 answers)
Closed 2 years ago.
I am new to using Mockito. In my logic I need to mock a function that is inside the loop and for every iteration, it should return different value.
Example :
for(value : values )
{
int i = getValue(value);
i=i+1;
}
if(i=somevalue)
{
some code
}
else
{
Some other code
}
So if I mock getValue() method to return a particular value. Everytime, it is returning the same value and only one part of if else is covered.
Can you please suggest me a way such that everytime in the loop getValue() is returned different value.
Thank you !
Since you have an input in getValue() you can use that.
when(mockFoo.getValue(value1).thenReturn(1);
when(mockFoo.getValue(value2).thenReturn(2);
when(mockFoo.getValue(value2).thenReturn(3);
But if you just don't care you can return different values in a sequence.
when(mockFoo.getValue(any()))
.thenReturn(0)
.thenReturn(1)
.thenReturn(-1); //any subsequent call will return -1
// Or a bit shorter with varargs:
when(mockFoo.getValue())
.thenReturn(0, 1, -1); //any subsequent call will return -1
Also please note, that if(i=somevalue) will always be true, you might want to use if (i == somevalue).

How do I call two functions inside an if statement that is inside a for loop in Java?

I am supposed to implement two functions that I already created (named isTargetWithinRange (what it does: given a target, this says whether a target is within range) and isTargetVisited (which checks that the target wasn't already captured)).
In this part, I am supposed to get the index of an unvisited target within the "range" (maximum distance to my target) of my current location. To do this, I am trying to create a for loop that contains an if-statement that calls my two variables.
The trouble that I am having is that I do not know how to call functions within the if-statement (that is within a for loop). I am trying to say within the if-statement that if isTargetWithinRange returns true or if isTargetVisited returns false, then the result is -1 (which in this case represents a target that is not yet captured).
if (isTargetWithinRange(i) return true || isTargetVisited(i) return false)
return -1;
}
}
I know that this question is probably incredibly confusing...but I really need help. I will try and clarify/define anything I can to get some help...
Something like this should do the job
if (isTargetWithinRange(i) || !isTargetVisited(i)) {
return -1;
}
You need to separate the method that returns true or false ( a predicate) from the action you want to take depending on the result. For example:
if(doIReturnTrue()) { // if true do something } .
The if statement will receive the result from the function, so you don't need
isTargetWithinRange(i) return true
Instead just pass the result of the method return into the if statement
if(isTargetWithinRange(i)){ // do if true etc }
To test a false result negate the return value using the logical not ! operator
if(!isTargetVisited(i)){ // do if true }
In the above when isTargetVisited returns false apply the 'logical not' to change this to true
I see that you might be new in Java. A function will return a value, in your case it is probably a boolean. Therefore you can use the following to achieve your result:
if (isTargetWithinRange(i) == true || isTargetVisited(i) == false) {
return -1;
}
Since the function will return a value, the == will check if the returned value is equal to what you want it to be.

Recursion using global variable in java

How do global variables work in case of recursion functions?
I have a code below. Why does this prints 7 0's as output?
int giValue=6;
public static void main(String[] args) {
// TODO Auto-generated method stub
Demo obj1=new Demo();
obj1.fnReverse();
}
public void fnReverse(){
if(giValue>0){
giValue--;
fnReverse();
}
System.out.println(" "+giValue);
}
I would like to know where the global variable value is getting saved, and how the value is changing?
Thanks
It prints 7 zeroes because at the end of each recursive call you are printing the value of giValue. Since the method never reaches the print statement until giValue reaches 0, it prints only 0s when the recursion unwinds.
The value is changing due to the giValue--; line. giValue is not a global variable. It's an instance variable of your Demo class, and its value is initialized to 6 when you create the Demo instance.
There are 7 calls to the method - the initial call and 6 additional recursive calls. The first 6 calls decrement giValue, so during the 7th call its value is 0 and the recursion ends.
#Eran described the reason why you get 7 0s.
it is normally wrong to use global variables within recursive method. but if you really insists of doing it then one of way of printing 0 1 ... 6 would be
public void fnReverse(){
int printMeInstead=giValue;
if(giValue>0){
giValue--;
fnReverse();
}
System.out.println(" "+printMeInstead);
}
NOTE:
THIS WILL ONLY WORK FORM PRIMITIVE DATATYPE ( because the actual value gets copied not a reference to an object)
Assuming you do understand the logical flow of the program.
givalue=6; (givalue--)=>5; call fnReverse(); //print statement not yet reached
givalue=5; (givalue--)=>4; call fnReverse(); //print statement not yet reached
.
.
.
givalue=1; (givalue--)=>0; call fnReverse(); //print statement not yet reached
Now,
when givalue=0; //givalue>0 evaluates to false; first print statement reached
prints givalue as 0.
Similarly, for all 6 previous calls the print statement correctly prints the current value of givalue, which apparently is now 0 since it is a global variable.
So, the output is 7 zeros.
class Demo{
int giValue=6;
public static void main(String[] args) {
// TODO Auto-generated method stub
Demo obj1=new Demo();
obj1.fnReverse();
}
public void fnReverse(){
System.out.println(" "+giValue);
if(giValue>0){
giValue--;
fnReverse();
}
//System.out.println(" "+giValue);
}
}
This code would print from 6 to 0 in descending order.See it here.

How to find the number of times a specific element occurs in an Array list in Java

I have written a method with the aim to count the number of times a specific flavour of crisps appears in a snack machine in blueJ
public int countPacks(String flavour){
int n = 0;
int nrFlavour = 0;
while( n < packets.size()) {
if( packets.get(n).equals(flavour)){
nrFlavour++;
n++;
}
else n++;
}
return nrFlavour;
}
I have an Arraylist 'packets' which holds PackOfCrisps objects which have a specific flavour. However when I have added say three packets of "salt" flavour crisps and I run this method, inputting "salt" as the flavour, it just returns 0 as though there are no PackOfCrisps objects with flavour "salt".
Sorry if this doesn't make sense. I am very new to Java and I have tried to explain my problem the best I can. :)
The list packets holds PackOfCrisps objects, and the method takes a String parameter. So the statement packets.get(n).equals(flavour) is comparing a PackOfCrisps object to a String, hence the count variable will never increase.
You need to compare the flavour string to the specific field of the object, something like:
if(packets.get(n).getFlavour().equals(flavour)){
On a side note, you can replace the while loop with a simple for loop and remove the increment of n.
There is a built-in solution to your problem, you can use this method
You can rewrite your countPacks method like this :
public int countPacks(String flavour){
return Collections.frequency(packets, flavour);
}

ConcurrentWeakKeyHashMap isEmpty method

The following is isEmpty() method from ConcurrentWeakKeyHashMap.java,
https://github.com/netty/netty/blob/master/src/main/java/org/jboss/netty/util/internal/ConcurrentWeakKeyHashMap.java
Why does it need mcsum, and what does the if(mcsum!= 0) {..} block doing ?
And more importantly, how do I get
if (segments[i].count != 0 || mc[i] != segments[i].modCount)
to evaluate to true?
public boolean isEmpty() {
final Segment<K, V>[] segments = this.segments;
/*
* We keep track of per-segment modCounts to avoid ABA problems in which
* an element in one segment was added and in another removed during
* traversal, in which case the table was never actually empty at any
* point. Note the similar use of modCounts in the size() and
* containsValue() methods, which are the only other methods also
* susceptible to ABA problems.
*/
int[] mc = new int[segments.length];
int mcsum = 0;
for (int i = 0; i < segments.length; ++ i) {
if (segments[i].count != 0) {
return false;
} else {
mcsum += mc[i] = segments[i].modCount;
}
}
// If mcsum happens to be zero, then we know we got a snapshot before
// any modifications at all were made. This is probably common enough
// to bother tracking.
if (mcsum != 0) {
for (int i = 0; i < segments.length; ++ i) {
if (segments[i].count != 0 || mc[i] != segments[i].modCount) {
return false;
}
}
}
return true;
}
EDIT:
Code to evaluate the above if block is now in ConcurrentWeakKeyHashMapTest
Essentially 1 thread continously monitors the concurrentMap, while another thread continuously add/remove same keypair value
This method is a copy of the same in Javas ConcurrentHashMap.
This kind of Map is using a modCount per segment to track during operations if it remained unchanged by different treads. During our traversal of the Map there could actually be other operations modifying the Map. This is called an ABA problem. We are asking the Map if it is empty and in fact it is not, but by accident it appears to be. A simple example:
Map with three segements
Segment 1: size=0
Segment 2: size=0
Segment 3: size=1
In this moment we decide to ask the Map and look into segment 1, which appears to be empty.
Now another algorithm comes and inserts an element to segment 1, but removes the other from segment 3. The Map was never empty.
Our Thread is running now again and we look into segment 2 and 3, both are empty. For us the Map is empty - as a result.
But for any empty slot we tracked whether it was modified, too. And for slot 3 we realize there have been modifications: mc[2]>=1 which means mcsum>=1. This means: since construction the Map was modified at least once. So to answer what mcsum is for: It is a shortcut for the default empty ConcurrentHashMap. If there never have been modifications, we do not need to check for concurrent modifications.
So we know something happened and check again each segment. If now a segment is empty we know what its modCount has been. For segment 3, lets say it was 1, for segment 1 it has been 0. Checking the modCount of segment 1 now it is 1 and the count is > 0 so we know that the Map is not empty.
Still there could be an ABA problem in the second loop as well. But because we know the modCounts we can catch any other concurrent algorithm changing something. So we say if the segment is empty and something changed with the modCount it has not been empty in the first place. That is, what the second loop is doing.
Hope this helps.
EDIT
And more importantly, how do I get
if (segments[i].count != 0 || mc[i] != segments[i].modCount)
to evaluate to true?
This evaluates to true if a segment contains something or if something was modified since the first loop. And it evaluates to false (which means: segment empty) if the segment contains nothing AND nothing was changed since the first loop. Or, to say it differently: We can be sure it has been empty all the time since looked on the checked segment first.
The mcsum checks if the map has ever been structurally modified. There appears to be no way to reset the modification counts to zero, so if the map has ever contained anything at all mcsum will be non-zero.
The weak keys are only cleaned up when the map is changed through a put, remove, et c, and they are only cleaned up within the modified segment. Retrieving values from the map does not clear up the weak keys. This means the map as implemented will hold many weak keys that have been garbage collected as they are only cleaned up if the same segment is modified.
This means results from the size() and isEmpty() methods will frequently return the wrong result.
With the API as provided your best recourse is to call purgeStaleEntries() prior to checking if the map is empty.

Categories