Distinguishing local variables with same name in a loop - java

I have found the following java code:
test:
for (int i = 0; i <= max; i++) {
int n = substring.length();
int j = i;
int k = 0;
while (n-- != 0) {
if (searchMe.charAt(j++) != substring.charAt(k++)) {
continue test;
}
}
foundIt = true;
break test;
}
System.out.println(foundIt ? "Found it" : "Didn't find it");
}
Inside the loop, the above code is creating 'n', 'j' and 'k' several times. How the program distinguishes between these variables of the same name?
I mean where they are stored in the memory to distinguish them?

With a bit of simplification:
Inside a { ... } block, int k = 0; creates a variable, and that variable exists up to the moment where you reach the end of the block, and there the variable gets destroyed. So, at any time during the program run, there's at most one n, j, or k in existence.
A bit closer to reality:
The compiler scans the whole method, finds the list of variables that might exist in parallel (i, n, j, k, and foundIt), and allocates enough places on the stack for these variables (5 places in your example). These stack places exist from the moment you enter your method until you return from it, but they are not used all the time, e.g. the k place only contains useful values from the time you execute int k = 0; to the end of the current loop iteration.

Java's local variables have a protection known as definite assignment this means that you can't read a value from them before you've assigned it a value.
They are also defined within a scope: you can only access the variable within a certain chunk of the program.
With the two of these things together, you don't need a separate variable for each iteration of the loop: you are guaranteed to assign a local variable a value before using it, so you are guaranteed to overwrite any value which was stored in it before, if any.
Variables are really just a helpful concept in the source code. Once compiled, the byte code doesn't have variable names: the compiler has simply determined that it can temporarily use a particular part of memory to store a value for a limited time. It will reuse this memory many times, but in ways that it guarantees do not overlap between usages.

Related

why my code give error of arrayIndex out of bound? [duplicate]

This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 3 months ago.
import java.util.Scanner;
public class recursion_4 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int a[] = new int[n];
for (int i = 0; i < n; i++) {
a[i] = sc.nextInt();
}
printArray(a, 0);
sc.close();
}
static void printArray(int arr[], int i) {
if (i == arr.length) {
return;
}
printArray(arr, ++i);
System.out.println(arr[i]);
}
}
I am try to print array element using recursion.
But it give error of arrayIndex Out of bound.
Replace ++i with i+1
You are incrementing the value of local variable in function. Instead of incrementing, send next value to other function as you will use that local variable value while printing in your function.
++i increments the value - it actually changes it (and evaluates as the updated value.)
++i, i++ and the subtle distinction between them has been the cause of many and frustrating bugs. This is just my opinion, but I advise never using either one of them except as a single-line statement when you need to increment something. The brevity isn't worth the risk of bugs.
So if you enter printArray with i=arr.length-1, then you get past your i guard, increment i, make the recursive call (which returns), and then try to access `arr[arr.length - 1 + 1], which is out of bounds.
If you're just learning about recursion, you might be confused at how local variables and returns work in a method. Each time you call a method, that's a new stack frame (a section of memory) with completely different values for its local variables, and which returns independently. i is not "i in every usage of the method named printArray", it's only "i in the current application of the method printArray." Similarly when you return, you cease to run the current application of printArray, but not every application.
Sorry if that part's all stuff you know - I find it's one of those things that's completely mind boggling to people starting out, and then becomes completely obvious a week later.

In for loops, does the length of the array get evaluated each iteration?

if I have a for loop like...
for (int i = 0; i < myArray.length; i++) { ... }
...does myArray.lengthget evaluated every iteration? So would something like...
int len = myArray.length;
for (int i = 0; i < len; i++) { ... }
... be a small performance increase?
regardless myArray.length is just a field so there is nothing to evaluate
Java array has length as public final int so it gets initialized once and when you refer to it there is no code execution like a method call
The public final field length, which contains the number of components of the array. length may be positive or zero.
The first form will probably incur some performance penalty, since evaluating it will require, before the iflt, an aload, an arraylength and an iload; whereas the second is only two iloads.
#ajp rightly mentions that myArray may change; so it is highly unlikely that the compiler will optimize the first form into the second for you (unless, maybe, myArray is final).
However, the JIT, when it kicks in, is probably smart enough so that, if myArray doesn't change, it will turn the first form into the second.
Just in case, anyway, use the second form (this is what I always do, but that's just out of habit). Note that you can always javap the generated class file to see the generated byte code and compare.
By the way, Wikipedia has a very handy page listing all of a JVM's bytecodes. As you may see, quite a lot of them are dedicated to arrays!
Yes, the termination expression gets evaluated every time. So you're right that storing the length once could be a small performance increase. But more importantly, it changes the logic, which could make a difference if myArray gets reassigned.
for (int i = 0; i < myArray.length; i++) {
if (something-something-something) {
myArray = appendToMyArray(myArray, value); // sets myArray to a new, larger array
}
}
Now it makes a big difference whether you store the array length in a variable first.
You wouldn't normally see code like this with an array. But with an arrayList or other collection, whose size could increase (or decrease) in the body of the loop, it makes a big difference whether you compute the size once or every time. This idiom shows up in algorithms where you keep a "To-Do list". For example, here's a partial algorithm to find everyone who's connected directly or indirectly to some person:
ArrayList<Person> listToCheck = new ArrayList<>(KevinBacon);
for (int i = 0; i < listToCheck.size(); i++) {
List<Person> connections = allConnections(listToCheck.get(i));
for (Person p : connections) {
if ([p has not already been checked]) {
listToCheck.add(p); // increases listToCheck.size()!!!
}
}
}
Not really. Both cases are comparing the value at two memory addresses with every iteration, except you are doing unnecessary assigning when you use a len variable. The performance difference is probably very small, and the first line is more readable, so I would use the first way as it is more readable. If you want to be even more readable and efficient, use a for-each loop if you are just going to do a linear iteration through your array. For-each loops look work like this:
int [] myArray = {1,2,3};
for(int i:myArray){
System.out.print(i);
}
will print:
1
2
3
as i is set to each element of the array. The for each loop can be used for many objects, and is a nice feature to learn.
Here is a guide explaining it.
https://www.udemy.com/blog/for-each-loop-java/

How to breakdown a method and process it [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am preparing for an exam next week, and I decided to look for some exam questions online for better preparation.
I came across this question and the answer is c. But I really want to know how or the step by step process to answer to answer a question like this. The part where I got stuck is trying to logically understand how a int m = mystery(n); How can a number equal a method? Whenever I get to a question like this is their anything important I should breakdown first?
private int[] myStuff;
/** Precondition : myStuff contains int values in no particular order.
/*/
public int mystery(int num)
{
for (int k = myStuff.length - 1; k >= 0; k--)
{
if (myStuff[k] < num)
{
return k;
}
}
return -1;
}
Which of the following best describes the contents of myStuff after the
following statement has been executed?
int m = mystery(n);
(a) All values in positions 0 through m are less than n.
(b) All values in positions m+1 through myStuff.length-1 are
less than n.
(c) All values in positions m+1 through myStuff.length-1 are
greater than or equal to n.
(d) The smallest value is at position m.
(e) The largest value that is smaller than n is at position m.
See this page to understand a method syntax
http://www.tutorialspoint.com/java/java_methods.htm
int m = mystery(n); means this method going to return int value and you are assigning that value to a int variable m. So your final result is m. the loop will run from the array's end position to 0. loop will break down when array's current position value is less than your parameter n. on that point it will return the loop's current position. s o now m=current loop position. If all the values of the loop is greater than n it will return -1 because if condition always fails.
Place the sample code into a Java IDE such as Eclipse, Netbeans or IntelliJ and then step through the code in the debugger in one of those environments.
Given that you are starting out I will give you the remainder of the code that you need to make this compile and run
public class MysteriousAlright {
private int[] myStuff;
public int mystery(int num)
{
for (int k = myStuff.length - 1; k >= 0; k--) {
if (myStuff[k] < num) {
return k;
}
}
return -1;
}
public static void main(String[] args) {
MysteriousAlright ma = new MysteriousAlright();
ma.setMyStuff(new int[] {4,5,6,7});
int m = ma.mystery(5);
System.out.println("I called ma.mystery(5) and now m is set to " + m);
m = ma.mystery(3);
System.out.println("I called ma.mystery(3) and now m is set to " + m);
m = ma.mystery(12);
System.out.println("I called ma.mystery(12) and now m is set to " + m);
}
public void setMyStuff(int[] myStuff) {
this.myStuff = myStuff;
}
}
You then need to learn how to use the debugger and/or write simple Unit Tests.
Stepping through the code a line at a time and watching the values of the variables change will help you in this learning context.
Here are two strategies that you can use to breakdown nonsense code like that which you have sadly encountered in this "educational" context.
Black Box examination Strategy
Temporarily ignore the logic in the mystery function, we treat the function as a black box that we cannot see into.
Look at what data gets passed in, what data is returned.
So for the member function called mystery we have
What goes in? : int num
What gets returned : an int, so a whole number.
There are two places where data is returned.
Sometimes it returns k
Sometimes it returns -1
Now we move on.
White Box examination Strategy
As the code is poorly written, a black box examination is insufficient to interpret its purpose.
A white box reading takes examines the member function's internal logic (In this case, pretty much the for loop)
The for loop visits every element in the array called myStuff, starting at the end of the array
k is the number that tracks the position of the visited element of the array. (Note we count down from the end of the array to 0)
If the number stored at the visited element is less than num (which is passed in) then return the position of that element..
If none of elements of the array are less than num then return -1
So mystery reports on the first position of the element in the array (starting from the end of the array) where num is bigger than that element.
do you understand what a method is ?
this is pretty basic, the method mystery receives an int as a parameter and returns an int when you call it.
meaning, the variable m will be assigned the value that returns from the method mystery after you call it with n which is an int of some value.
"The part where I got stuck is trying to logically understand how a int m = mystery(n); How can a number equal a method?"
A method may or may not return a value. One that doesn't return a value has a return type of void. A method can return a primitive value (like in your case int) or an object of any class. The name of the return type can be any of the eight primitive types defined in Java, the name of any class, or an interface.
If a method doesn't return a value, you can't assign the result of that method to a variable.
If a method returns a value, the calling method may or may not bother to store the returned value from a method in a variable.

Understanding basic recursion function in Java to calculate positive integers in array

I am trying to learn recursion in Java and have an array that takes in continuous input until the Scanner reads in a 0.
From there I have a method that (attempts) to calculate the number of positive integers in the array using recursion. This is the first recursive function I have ever written and I keep getting a stackoverflow error.
I have read tutorials and I still can't wrap my head around the basic understanding of recursion.
public class reuncF {
private static int start = 0;
private static int end = 98;
public static void main(String[] args) {
input = input.nextDouble();
list[i] = numInput;
computeSumPositive(numList, count);
}
}
return positives += solve(numbers, count++);
}
}
You forgot to stop your recursion!
There has to be some case where computeSumPositive returns without calling itself again. Otherwise it'll just keep going forever, never getting back to you.
If you did it with a loop, the loop would look like this:
int positives = 0;
for (int i = 0; i < numList.length; ++i) {
if (numList[i] > 0) {
positives++;
}
}
To do that recursively, you just find out what are the variables used in the loop. They are i, numList and positives.
computeSumPositive(int i, double[] numList, int positives)
Then we take a look at what the loop does. First, it checks whether we went too far,
so our recursive function should do that too. It'll have to return instead of just falling through like the loop does. And obviously, it must return the result:
{
if (! (i < numList.length))
return positives;
The loop then does the test and maybe increments positives, so the recursive function should also do that:
if (numList[i] > 0) {
positives++;
}
At the end of the loop, i is updated:
i++;
The loop just starts over, but the recursive function will have to call itself. Of course, we want it to use the new value of i and positives, but fortunately we updated those, so now we can just do:
return computeSumPositives (i, numList, positives);
}
The tricky bit is that the values i, numList, and are local to each call. Each invocation of computeSumPositives can see only the arguments it were given. If it changes them, none of the other invocation can see that change.
EDIT: So if we, for reasons we can only speculate about, wanted desperately for computeSumPositive to take only 2 parameters, we would have to "split up" positives across each invocation. Each invocation knows whether or not its number was positive or not; all we have to do is add them. Then it looks like this:
computeSumPositive(int i, double[] numList)
{
if (! (i < numList.length))
return 0; // I didn't find any at index i
if (numList[i] > 0) {
// Theres one I found + however many my later
// invocations will find.
return 1 + computeSumPositive (i+1, numList);
} else {
// I didn't find any, but my later invocations might.
return computeSumPositive (i+1, numList);
}
}
I find it helpful, when dealing with recursion, to figure out the termination case first.
It looks like you are treating 'count' as an index. So you could check if your at the last index in the array, if so and if the value is positive return a 1, if the value is non-positive return a 0 - dont recurse anymore.
If your not at the last index, and the value is positive return a 1 + the recursive function call, or if the value is non-positive just continue to recurse.
This will still cause a stack overflow for large arrays.
The value of count++ is the same as the value of count; the program uses the value and then increments it. But the result is that computeSumPositive keeps calling itself with the same value of count, which leads to infinite recursion. Note that each time computeSumPositive calls another computeSumPositive, each call has its own copy of the parameters (like count) and the local variables; so incrementing one computeSumPositive's copy of count has no effect on the value of count used by other recursive calls.
Change count++ to count + 1, and also add a way to halt the recursion. (At some point, you will be calling computeSumPositive to look at zero integers, and at that point, it should just return 0 and not call itself. You need to think about: how do you test whether you've reached that point?)

How to detect an infinite loop in a recursive call?

I have a function that is recursively calling itself, and i want to detect and terminate if goes into an infinite loop, i.e - getting called for the same problem again. What is the easiest way to do that?
EDIT: This is the function, and it will get called recursively with different values of x and y. i want to terminate if in a recursive call, the value of the pair (x,y) is repeated.
int fromPos(int [] arr, int x, int y)
One way is to pass a depth variable from one call to the next, incrementing it each time your function calls itself. Check that depth doesn't grow larger than some particular threshold. Example:
int fromPos(int [] arr, int x, int y)
{
return fromPos(arr, x, y, 0);
}
int fromPos(int [] arr, int x, int y, int depth)
{
assert(depth < 10000);
// Do stuff
if (condition)
return fromPos(arr, x+1, y+1, depth + 1);
else
return 0;
}
If the function is purely functional, i.e. it has no state or side effects, then you could keep a Set of the arguments (edit: seeing your edit, you would keep a Set of pairs of (x,y) ) that it has been called with, and every time just check if the current argument is in the set. That way, you can detect a cycle if you run into it pretty quickly. But if the argument space is big and it takes a long time to get to a repeat, you may run out of your memory before you detect a cycle. In general, of course, you can't do it because this is the halting problem.
You will need to find a work-around, because as you've asked it, there is no general solution. See the Halting problem for more info.
An easy way would be to implement one of the following:
Pass the previous value and the new value to the recursive call and make your first step a check to see if they're the same - this is possibly your recursive case.
Pass a variable to indicate the number of times the function has been called, and arbitrarily limit the number of times it can be called.
You can only detect the most trivial ones using program analysis. The best you can do is to add guards in your particular circumstance and pass a depth level context. It is nearly impossible to detect the general case and differentiate legitimate use of recursive algorithms.
You can either use overloading for a consistent signature (this is the better method), or you can use a static variable:
int someFunc(int foo)
{
static recursionDepth = 0;
recursionDepth++;
if (recursionDepth > 10000)
{
recurisonDepth = 0;
return -1;
}
if (foo < 1000)
someFunc(foo + 3);
recursionDepth = 0;
return foo;
}
John Kugelman's answer with overloading is better beacuse it's thread safe, while static variables are not.
Billy3
Looks like you might be working on a 2D array. If you've got an extra bit to spare in the values of the array, you can use it as a flag. Check it, and terminate the recursion if the flag has been set. Then set it before continuing on.
If you don't have a bit to spare in the values, you can always make it an array of objects instead.
If you want to keep your method signature, you could keep a couple of sets to record old values of x and y.
static Set<Integer> xs;
static Set<Integer> ys;//Initialize this!
static int n=0;//keeps the count function calls.
int fromPos(int [] arr, int x, int y){
int newX= getX(x);
int newY= getY(y);
n++;
if ((!xs.add(Integer.valueOf(newX)) && !ys.add(Integer.valueOf(newY))){
assert(n<threshold); //threshold defined elsewhere.
fromPos(arr,newx,newy);
}
}
IMHO Only loops can go into an infinite loop.
If your method has too many level of recursion the JVM will throw a StackOverflowError. You can trap this error with a try/catch block and do whatever you plan to do when this condition occurs.
A recursive function terminates in case a condition is fulfilled.
Examples:
The result of a function is 0 or is 1
The maximum number of calls is reached
The result is lower/greater than the input value
In your case the condition is ([x0,y0] == [xN,yN]) OR ([x1,y1] == [xN,yN]) OR ([xN-1,yN-1] == [xN,yN])
0, 1, ...N are the indexes of the pairs
Thus you need a container(vector, list, map) to store all previous pairs and compare them to the current pair.
First use mvn findbugs:gui to open a gui which point to the line where this error is present.
I also faced the same problem and I solved it by adding a boolean variable in the loop verification.
Code before ->
for (local = 0; local < heightOfDiv; local = local + 200) { // Line under Error
tileInfo = appender.append(tileInfo).append(local).toString();
while (true) {
try {
tileInfo = appender.append(tileInfo).append(getTheTextOfTheElement(getTheXpathOfTile(incr))).toString();
incr++;
} catch (Exception e) {
incr = 1;
tileInfo = appender.append(tileInfo).append("/n").toString();
}
}
To Solve this problem, I just added a boolean variable and set it to false in the catch block. Check it down
for (local = 0; local < heightOfDiv; local = local + 200) {
tileInfo = appender.append(tileInfo).append(local).toString();
boolean terminationStatus = true;
while (terminationStatus) {
try {
tileInfo = appender.append(tileInfo).append(getTheTextOfTheElement(getTheXpathOfTile(incr))).toString();
incr++;
} catch (Exception e) {
incr = 1;
tileInfo = appender.append(tileInfo).append("/n").toString();
terminationStatus = false;
}
}
This is how i Solved this problem.
Hope this will help. :)

Categories