Is it possible to retain information via a helper function with java, without using static variables.
For example,
public void foo(){
int v = 0;
fooHelper(2);
}
public void fooHelper(int depth){
v++;
fooHelper(depth-1)
}
Namely I want to update variable v without loosing the information for each recursive case, without having to access a variable outside the function.
Forget about all the answers that tell you to declare attributes, or to update mutable objects in each recursive call. In a true functional, recursive style you "retain" information by passing it as parameters and/or return types.
Let me illustrate with a simple example, let's say that you want to recursively calculate the sum of the elements in an int[]. Here, the state (the information that needs to be retained between recursive calls) is the current index in the array and the sum so far. Here's how to do it:
public int sum(int[] array) {
return sum(array, 0, 0);
}
private int sum(int[] array, int idx, int acc) {
if (idx == array.length)
return acc;
return sum(array, idx+1, acc+array[idx]);
}
Call it like this:
int[] array = {1, 2, 3};
System.out.println(sum(array));
As you can see, there's no need to declare (static or instance) attributes, and no need to pass and modify mutable objects (lists, maps) - I'm not even using local variables, because all the required information needed to solve the problem is present as method parameters.
In the code in your question the v variable is supposed to do what the acc parameter is doing in my answer, namely: modifying an accumulated value each time the recursion is called. In the end, you just need to return the accumulated value from the helper function (which must not have a void return type) and that's how you'll get the value in foo().
A variable declared in a scope (for example method) is accessible only in this scope (e.g. not in another method).
If the information is relevant for the method only, keep the variable in the method. If the information is relevant for the whole object / class state, keep it a class member (static/non static).
For example:
public void someRecursiveMethod(int num) {
while (num < 10) {
num++;
someRecursiveMethod(num);
System.out.println("Current num = " + num);
}
}
You can create a new class (yuck), or pass the variable as a parameter and return it in fooHelper.
Why not make it an instance variable(not necessarily static)...??
public class Recursive {
int v = 0;
public void foo(){
fooHelper(2);
System.out.println(v);
}
public void fooHelper(int depth){
v++;
if(depth-1!=0)//Added this because I was getting an StackOverflowError
fooHelper(depth-1);
}
public static void main(String[] args) {
Recursive r = new Recursive();
r.foo();
}
}
You could return a list or a similar data structure:
public List<Integer> fooHelper( int v, int depth ){
if( depth == 0 ) return new ArrayList();
v++;
List<Integer> result = fooHelper( v, depth-1 );
result.add( new Integer(v) );
return result;
}
Because the variable v is of primitive type, changes made to it will not be visible outside the function scope. You could declare the variable v inside a class, say State and pass the state object into the recursive function to get the required effect.
public void foo(){
State state = new State();
fooHelper(state, 2);
}
public void fooHelper(State state, int depth){
state.v++;
fooHelper(state, depth-1);
}
class State {
int v;
}
Hope it helps.
You can pass an object to store the update for each recursive call. Something like the one below.
public static void fooHelper(int depth, HashMap map){
map.put(depth, "Call " + depth);
if (depth > 0)
{
fooHelper(depth-1, map);
}
return;
}
I think this is called memoization. It looks like
class Fibonacci
{
public Map < Integer , Integer > memorized = new HashMap < > ( ) ;
public int fib ( int n )
{
if ( memoized . containsKey ( n ) )
{
return memoized . get ( n ) ;
}
else
{
int fib = // calculate recursively
memoized . put ( n , fib ) ;
return fib ;
}
}
}
You should be able to get decent (not optimal) performance out of this algorithm. The primary reason that the recursive fibonacci algorithm has horrible performance is b/c it is repeatedly calculating the same values. With recursion+memoization it never calculates any value more than once.
Thanks to #Aristide for pointing out the subtle difference between memorization and memoization.
Related
So I understand how to use a recursive method that has some other return type other than void. Typically I would call the same method again in the same method( inside the recursive case), while decremented or increment some value in the call to reach the base case. Then at some point the base case is reached and the problem is solved, so it starts returning the value from every call. Along those lines.
BUT
What if the method has the return type void, so you can't call the method as it won't/can't return anything? I'm trying to write a sentence backwards, which I've solved both with a for loop and a resucrive method that can return a string value, but I'm not sure how to approach it if it's void which is what the assignment is asking for.
Edit: I should also mention the sentence can only be passed in the parameter
Thank you everyone for the information and the help!
Recursion doesn't work only with methods/functions that return values. Recursion means only that the method/function calls itself.
You must guarantee that there is at least one stop condition but this does not require the function to return a value. This is commonly achieved by incrementally changing one or more arguments that you pass each time the function recursively calls itself. When that/those arguments satisfy a certain condition your function no longer calls itself and all pending operations are solved.
I am not fully aware of the task you are trying to do but here is an example of a recursive function that writes a string backwards. I use PSEUDO-functions with names that hopefully are self-explanatory.
public void writeBackwards(String str) {
// This is the negation of the stop condition, so the stop condition
// is when the string is empty, in which case this function will do
// nothing:
if (!str.isEmpty()) {
char firstCharacter = str.getFirstCharacter();
str = str.removeFirstCharacter();
writeBackwards(str); // the recursive call
// The following operation will be pending, waiting for the
// recursive call to be resolved first:
writeCharacter(firstCharacter);
}
}
You can use any mutable Object as a parameter of the recursive function to store the result. For example, the backwards-sentence problem you mentioned could be written as:
public void stringReverse(String s, int index, StringBuilder sb) {
if (index < 0)
return;
sb.append(s.charAt(index));
stringReverse(s, index - 1, sb);
}
And called like this
StringBuilder sb = new StringBuilder();
stringReverse(mySentence, mySentence.length() - 1, sb);
Just like in C++ you can pass in pointers, here in Java you can simply pass in a class object to your function to hold the value generated from the recursive calls of the function. A simple example reflecting your question to compute fibonacci number is following.
public class ComputeFibonacci {
static class Fibonacci {
public int ith;
public int value;
Fibonacci(int a, int b) {
ith = a;
value = b;
}
}
private static void fibonacci(Fibonacci result) {
if (result.ith == 1 || result.ith == 2) {
result.value = 1;
} else {
Fibonacci left = new Fibonacci(result.ith - 1, 0);
Fibonacci right = new Fibonacci(result.ith - 2, 0);
fibonacci(left);
fibonacci(right);
result.value = left.value + right.value;
}
}
public static void main(String[] args) {
// Here we compute the 10th fibonacci number
Fibonacci f = new Fibonacci(10, 0);
fibonacci(f);
System.out.println("The result is " + f.value);
}
}
Good luck.
I'll preface my question with the statement that I am very new to Java, so I apologise if my code is totally disgusting to read.
What I'm trying to do: I'm writing a program that takes two integers from the user, a low value and a high value, and sends both integers to two different methods. Method #1 has a simple for loop and should print out all of the numbers between the lowest number and the highest number that are multiples of 3 or 5, and Method #2 does the same except for numbers that are multiples of 3 or 5 it also checks if that number is also a multiple of 6 and, if so, it prints the number and an asterisk next to it.
What I'm having trouble with: I'm pretty stumped on what I need to return from my methods & how to return anything at all. This is the first time I've worked on a method properly (just moved up from "Hello World) and from what I can see I don't really need to return anything at all. All the code that I've put in my methods pretty much complete the program, so I thought maybe returning the integers I sent would be enough, apparently it's not. So, without further ado, here's my code.
The Error:
javac BonusQ.java
.\MethodOne.java:19: error: illegal start of type
return(int lowestRange, int highestRange);
^
.\MethodTwo.java:36: error: illegal start of type
return(int lowestRange, int highestRange);
^
The Main:
import java.util.Scanner;
public class BonusQ
{
public static void main(String [] args)
{
Scanner scan = new Scanner(System.in);
int lowestRange = 0;
int highestRange = 0;
System.out.println("Enter the lowest integer in your range");
lowestRange = scan.nextInt();
System.out.println("Enter the highest integer in your range");
highestRange = scan.nextInt();
MethodOne.NoAsterisk(lowestRange, highestRange);
MethodTwo.Asterisk(lowestRange, highestRange);
}
}
MethodOne:
public class MethodOne
{
public static int NoAsterisk(int lowestRange, int highestRange)
{
for(int i = lowestRange; i <= highestRange; i++)
{
if (i%5 == 0)
{
System.out.println(i);
}
else if (i%3 == 0)
{
System.out.println(i);
}
}
}
return(int lowestRange, int highestRange);
}
MethodTwo:
public class MethodTwo
{
public static int Asterisk(int lowestRange, int highestRange)
{
for(int i = lowestRange; i <= highestRange; i++)
{
if (i%5 == 0)
{
if (i%5 == 0 && i%6 == 0)
{
System.out.println(i + "*");
}
else
{
System.out.println(i);
}
}
else if (i%3 == 0)
{
if (i%3 == 0 && i%6 == 0)
{
System.out.println(i + "*");
}
else
{
System.out.println(i);
}
}
}
}
return(int lowestRange, int highestRange);
}
Sorry if the post is a bit beefy to read, I just find that adding my thoughts on the code might help you explain to me what's going wrong, seeing as you may not know the extent of my incompetence :)
Thanks in advance.
Ok, Classes have members.
Members are either some variables or arrays of variables
and the methods of a class.
So you got
public class MyMethod
{
public static int Asterisk(int loRange, int hiRange)
{
// Do magic let's make a sum for this example
// You enter loRange and hiRange (you defined it above)
return loRange + hiRange // Here the method returns a result
}
}
// So then....
public static void main(String [] args)
{
// WHATEVER IS IN HERE RUNS ALWAYS FIRST.
z = Asterisk(1,2); // 1 and 2 is lo and hi range values ;)
// Z has a value of 3 now because Asterisk(1,2) returns 1 + 2
}
See how this works?
Now this works because you use the static definition (meaning there must not be an instance of MyMethod created first to use the method. It's not wrong, but if you can make a program do things with class instances, you better do it that way.
You make an instance of a class, this is called an object, using a special method. This method has the exact name of the Class and constructs an instance of it.
You should study now about constructors, abstract classes etc etc.
I can't say you do it wrong or right either. It is about what the program is all about and you should study the scope for variables and methods, and the encapsulation concept of Object Oriented Programming.
Using only static methods, goes against encapsulation principle, it is possibly wrong but I can't tell for sure.
I hope this helped you and gave you a good direction to go on with your study.
PS:
To return multiple results, you should return an array of variables, not just a variable.
You can also return nothing and just have it do the job to a needed array. This FORCES you though to make this array public. (Not a good practice)
Finally if multiple value returns are needed to just print them on the console... well, just do it in the method, no need to return anything really.
You don't need to return anything, being that the methods are printing out all the values.
You can change them into void methods, for example:
public static void asterisk(int lowest, int highest) {
//loops and if statements
//no return statement!
}
The code in the methods will run and voila, you are done!
EDIT: That being said, there's a lot more than can be done to make this code more Java-like, but for now this will work.
mmmmm...you can return types, and (int lowestRange, int highestRange) its not a type. Look at the method definition
public static int Asterisk(int lowestRange, int highestRange)
the return type is declared as int, so you should return an int value. You can do something like
return lowestRange;
return 1;
with that in consideration, the error should dissapear. The question is, why do you need to return a value? From what i've read, your methods are supose to print stuff, not to return stuff...
The return statements are out of the method. You have to put them before the close method brackets.
public class MyClass{
public int sum (int a, int b){
return a + b;
} // The return have to be before this brackets
}
My professor gave me a code for the methods to be used in sorting an array of names lexicographically, but I have no idea how what to write inside the main class to show that the program works. I am very new to java, so please if you know how to do this could you write it as simple as possible for me to understand it. Thanks in advance.
This is are the classes
public class quicksort_class {
int[] array1 = new int[11];
public quicksort_class(int[] w)
{
array1 = w;
}
private static void sort(String[] string, int leftlimit, int rightlimit) {
if (rightlimit > leftlimit)
{
int midpoint = partitionstep(string, leftlimit, rightlimit);
sort(string, leftlimit, midpoint - 1);
sort(string, midpoint, rightlimit);
}
}
public static int partitionstep(String[] string, int leftlimit, int rightlimit)
{
String midpoint = string[rightlimit];
int lpointer = leftlimit;
int rpointer = rightlimit;
String temp = "";
while(string[lpointer].compareTo(midpoint) <= 0)
{
lpointer = lpointer ++;
}
while(string[rpointer].compareTo(midpoint) > 0)
{
rpointer = rpointer --;
}
if(lpointer > rpointer)
{
temp = string[lpointer];
string[lpointer] = string[rightlimit];
string[rpointer] = temp;
System.out.println(string);
}
while(lpointer < rpointer)
{
temp = string[lpointer];
string[lpointer] = string[rightlimit];
string[rightlimit] = temp;
}
return lpointer;
}
}
This is the main class (as you can see I have no idea what to write)
package quicksort;
public class Quicksort {
public static void main(String[] args) {
}
}
Write something that sets up an array of strings and calls sort against it, then prints out the results or checks them against a known good result.
Ideally, write something which does this repeatedly, with particular emphasis on checking unusual combinations (already sorted or sorted in reverse, null in the array, same value appearing several times or all values being identical...)
If you want to go beyond that, you need to dig into the code to understand its edge cases and specifically test those, and/or do a "code coverage" analysis (there are tools to help with that) to make sure all parts of the code have been exercised.
Assume the algorithm of sort method is correct:
1. If the main method is within the body of quicksort_class, you can directly call the sort method as sort(arrayToBeSorted, 0 , arrayToBeSorted.length-1). And the arrayToBeSorted should ordered lexicographically after your call. You can check that to confirm.
2. If the main method is in other class, as your main method currently, you need to at least change the private prefix of sort method to public, and call quicksort_class.sort(arrayToBeSorted, 0 , arrayToBeSorted.length-1).
Some tips:
1. Private prefix of method definition means this method can only be called inside current class body.
2. Static prefix of method definition means you should call this method via class name directly, instead of via a instance of class.
By the way, can you provide what the array1 attribute stands for? I don't get why it's there.
Is it a good practice to use properties as local variable. In cases where there are many methods which uses some variables, In each method the variable value changes. This avoids many times creating new variables and the code increases. Any suggestion?
private void method1(){
int totalLength = length1 + 10;
int totalBreath = (breath1 + breath2) + 20;
int size = (totalLength * totalLength);
System.out.println(size);
}
private void method2(){
int totalLength = length1 + 20;
int totalBreath = (breath1 + breath2) + 30;
int size = (totalLength * totalLength);
System.out.println(size);
}
private void method3(){
int totalLength = length1 + 60;
int totalBreath = (breath1 + breath2) + 10;
int size = (totalLength * totalLength);
System.out.println(size);
}
As you can see, totalLength, totalBreath, size is repeated in every method. Can i make them as fields of the class? So, i need not declare it in every method.
private void method1(){
totalLength = length1 + 10;
totalBreath = (breath1 + breath2) + 20;
size = (totalLength * totalLength);
System.out.println(size);
}
I read your question as, "When should a local variable be promoted to be a field of the class?"
The best answer is "it depends" but then again, its accuracy is quickly eclipsed by its lack of usefullness.
Fields should have a relationship to the class itself, as in is the field an attribute of the class? I include an example below to illustrate the syntax difference, but I agree with this post that it should be avoided if it pollutes the meaning of the class.
Usually you only need to have a field when you need the value of the field to be maintained between calls to different methods for a given instance of the class, with the option of making it static when the value should be maintained between method calls for all instances of the class. It will depend on several factors like shop convensions, performance goals, existing codebase, etc. so there is no single right answer without specific code. This question seems to include similar points. If you find yourself using the approach below, you might consider other approaches like refactor the behavior into a help class.
Another question asks the same question but from the perspective of a programming student.
Examples:
public class VariableScope {
int field1 = 3;
void foo() {
int a = 2;
// variable passing in width
bar1(1);
bar2(1);
// variable passing in depth
bar3(a);
// uses a field to reduce variable passing
baz1();
baz2();
}
void bar1(int param) {
System.out.println("param=" + param);
}
void bar2(int param) {
System.out.println("param=" + param);
}
void bar3(int param)
{
System.out.println("Passing param to bar4");
bar4(param);
}
void bar4(int param){
System.out.println("param=" + param);
}
void baz1() {
System.out.print("field1=" + field1);
}
void baz2() {
System.out.print("field1=" + field1);
}
}
From what it sounds like, if you're using the variable for multiple methods you're should declare the variable as a global variable. But yes, If no other method needs that variable , and you don't want to be writing a bunch of return statements you can use local variables
I suppose you mean a field by property which usually has accessor and mutator (get,set-methods).
In common you should keep the scope of a variable as small as possible. An example if you use many for loops like:
for ( int i = 0 ; i < 10 ; i++ ) {
}
and replace this by
int i;
method1() {
for ( i = 0 ; i < 10 ; i++ ) {
// some code;
}
}
method2() {
for ( i = 0 ; i < 10 ; i++ ) {
// some code;
}
}
If one thread calls method1() and another one method2() you would face a race condititon.
You can easily introduce hard to find bugs in your code.
I assume you mean something like this:
Class foo() {
int x;
public bar() {
for(x = 0; x <100; ++x) ...
} }
No, it's not good practice.
One place where it can even be harmful is in the synchronization/concurrency/multi-threaded case: if you are working with class members, they are going to need be synchronized which will eat into performance. Otherwise you risk multiple threads overwriting the value of the field and that can lead to errors in your program (likely hard to debug).
Sorry for the silly question, but I cannot seem to find an answer on google. I have written a class, and within the class there is a constructor which creates an arraylist, in the same class there is a method which iterates through the array list by creating an iterator object. As my code stands, however, it is not recognizing the arraylists name, should I store the array list in a class variable, or pass it into the method as an argument ?
What is usually best practice here as this is something that is always getting me ?
My code is as follows if you can't follow my somewhat convuluted explanation ! Apologies ! Thanks a lot for reading :)
import java.util.*;
public class Primes {
public Primes( int initialCapacity) {
ArrayList<Integer> listOfPrimeNumbers = new ArrayList<Integer>(initialCapacity);
//how do I get the above...
int index = 2;
while (index != listOfPrimeNumbers.size())
{
if (isPrime(index))
{
listOfPrimeNumbers.add(index);
}
index++;
}
}
public static boolean isPrime(int candidateNo) {
Iterator<Integer> iter = listOfPrimeNumbers.iterator( );
//in here ! ?
i=2;
while ( iter.hasNext( ) ) {
if (candidateNo%i==0 && i!=1) {
return false;
}
else
return true;
}
}
(Also, if you see anything horrifically wrong with my code please don't be afraid to call me out on it, the more constructive criticism the better!)
}
You define a private var for your ArrayList and initalize this variable in your Constructor.
Now you can access the list inside your Class :)
hope that helps.
import java.util.*;
public class Primes {
private ArrayList<Integer> listOfPrimeNumbers;
public Primes( int initialCapacity) {
listOfPrimeNumbers = new ArrayList<Integer>(initialCapacity);
//how do I get the above...
int index = 2;
while (index != listOfPrimeNumbers.size())
{
if (isPrime(index))
{
listOfPrimeNumbers.add(index);
}
index++;
}
}
public static boolean isPrime(int candidateNo) {
Iterator<Integer> iter = listOfPrimeNumbers.iterator( );
//in here ! ?
i=2;
while ( iter.hasNext( ) ) {
if (candidateNo%i==0 && i!=1) {
return false;
}
else
return true;
}
}
listOfPrimeNumbers is a local variable. You can either change it into a static member of the class, make it an instance variable and make isPrime non-static, or pass it as a parameter to isPrime.
Given the apparent intent of this class I'd make isPrime non-static and make listOfPrimeNumbers an instance variable.
You need to reconsider how your class is put together:
Having all the work done within the constructor is typically not a good idea. Constructors in Java are tricky, generally I try to make them as simple as possible, and have the real work go elsewhere.
Static methods are overrated, I try to avoid them. If you have some data structure you want your methods to access, make those methods instance methods and have the data structure be an instance variable. Java is supposed to be an object-oriented language, using static methods prevents object-orientation and restricts your options.
Think about how you want to use the class, and how you'd like to test it, and change the API implemented by the class to match that.
It seems you want to set the arraylist as a class member variable. However you're declaring isPrime as static. Those 2 things don't make sense together. If isPrime doesn't need to be static then simply store the arraylist as a class member. If it DOES need to be static (for whatever reason), you'll need to NOT have a constructor (because it wouldn't make sense with isPrime being static in this case) and create the arraylist somewhere else and pass it as an argument to isPrime.
Edit: on second thought, you don't need isPrime to be static, It should look like this:
public class Primes {
ArrayList<Integer> listOfPrimeNumbers;
public Primes( int initialCapacity) {
listOfPrimeNumbers = new ArrayList<Integer>(initialCapacity);
//how do I get the above...
int index = 2;
while (index != listOfPrimeNumbers.size())
{
if (isPrime(index))
{
listOfPrimeNumbers.add(index);
}
index++;
}
}
public static boolean isPrime(int candidateNo) {
Iterator<Integer> iter = listOfPrimeNumbers.iterator( );
//in here ! ?
i=2;
while ( iter.hasNext( ) ) {
if (candidateNo%i==0 && i!=1) {
return false;
}
else
return true;
}
}
However it seems like you have other problems. How will your while loop in your constructor ever end? You're incrempending index every time, but you're only adding something to your list if it's prime.
And in your isPrime method, what's the point of your while loop? You call iter.hasNext(), but don't use what its iterating over. You only ever check candidateNo and i.