This question already has answers here:
Are arrays passed by value or passed by reference in Java? [duplicate]
(7 answers)
Closed 6 years ago.
Background
I am making an array tools class for adding Python functionality to a Java array, and I came across this problem. This is obviously a simplified, more universal version.
Question
In this example:
public class ArrayTest
{
public static void main(String[] args)
{
// initial setup
int[] given = {1, 2, 3, 4, 5};
// change array
int[] changed = adjust(given);
// these end up being the same...
System.out.println(Arrays.toString(changed));
System.out.println(Arrays.toString(given));
}
private static int[] adjust(int[] a)
{
for (int i = 0; i < a.length; i++)
{
a[i]++;
}
return a;
}
}
...why is changed and given the same thing?
Disclaimer
I am guessing that this has been asked before, but I couldn't find an answer, so I apologize for that.
When you do
int[] given = {1, 2, 3, 4, 5};
given's value is called an object reference. It's a value telling the JVM where that array is, elsewhere in memory. given doesn't contain the array (like it would an int), it contains a reference to the array (e.g., like an address). E.g.:
+−−−−−−−−−+
[given:Ref88465]−−−−>| (array) |
+−−−−−−−−−+
| 0: 1 |
| 1: 2 |
| 2: 3 |
| 3: 4 |
| 4: 5 |
+−−−−−−−−−+
When you call adjust(given), you're passing a copy of the value of given into adjust. That copy still points to the same place in memory. E.g., during the call to adjust, we have two copies of that object reference, both pointing to the same single array:
+−−−−−−−−−+
[given:Ref88465]−−−−>| (array) |
/ +−−−−−−−−−+
| | 0: 1 |
| | 1: 2 |
| | 2: 3 |
| | 3: 4 |
| | 4: 5 |
| +−−−−−−−−−+
[a:Ref88465]−−−−−−+
When you change the contents of the array, you're modifying the state of array. When adjust returns and you assign the result to changed, you have:
+−−−−−−−−−+
[given:Ref88465]−−−−−>| (array) |
/ +−−−−−−−−−+
| | 0: 2 |
| | 1: 3 |
| | 2: 4 |
| | 3: 5 |
| | 4: 6 |
| +−−−−−−−−−+
[changed:Ref88465]−+
If you want a copy of the array with the changes, you'll need to make a copy of it, for instance via arraycopy. Both copying and changing-in-place are used in practice, depending on the use case.
what you are doing is sending the address of your array to your method , so what was changed is your original array and you just return it( the address of your array) so any change you have done on that array(memory) will be reflected in both variables as both are pointing to the same memory location
Related
Below is a function which takes int and return int. Within the function I call the function itself and if i==1, I want to go out of my function.
Basically I'm trying to calculate factorial in recursive manner.
Code Snippet
static int factorial(int i){
result = result * i;
if(i==1){
return 0;
}
factorial(i-1);
return 1;
}
Note - result is an global int variable and is initialize to 1.
Why this function returns 1 instead of 0.
[Note when i==1 then with return statement the pointer should come out of the function]
Please don't post better algorithm for factorial, I'm looking for - why this code is behaving a bit different.
Your code doesn't even compile as result isn't defined.
Then, the method could return either 0 or 1, nothing else regarding the return you wrote, so you can't expect to get real values.
Then the real algorithm
for 0 or 1, return 1
else return the value multiplied by the factorial(previous)
static int factorial(int i) {
if (i <= 1) { // for 0 or 1
return 1;
}
return i * factorial(i - 1);
}
example calling factorial(3):
int i = factorial(3);
+--------------------------------------------------+
|result = result * 3; |
|if (i==1) { |
| // not executed |
|} |
|factorial(2); |
| +-------------------------------------------+ |
| |result = result * 2; | |
| |if (i==1) { | |
| | // not executed | |
| |} | |
| |factorial(1); | |
| | +---------------------------------+ | |
| | |result = result * 1; | | |
| | |if (i==1) { | | |
| | | return 0; | | |
| | |// nothing more in factorial(1) | | |
| | +---------------------------------+ | |
| |// factorial(1) returned 0 (value not used)| |
| |return 1; // factorial(2) | |
| +-------------------------------------------+ |
|// factorial(2) returned 1 (value not used) |
|return 1; // factorial(3) |
+--------------------------------------------------+
i = 1; // the value returned by last call
factorial(3) returns 1! recursion was terminated by return 0, but that value is not being used
Zero would have been returned if the last two lines were joined to return factorial(i-1);
only factorial(1) will return 0, e.g. int i = factorial(1)
Because u are not returning 0. Your function will always return 1 which is the returned value of the first call. All the other recursive function calls are being made but not being used to return by the parent function. For example if you call factorial(5) then all the recurring calls (from 4 to 1) would execute and process the "result" variable but you will only get the returned value of factorial(5) which is always going to be 1.
The fundamental problem with your code is that it is confused about how it wants to return data.
You have a result global variable which is supposed to be how this function 'communicates' the answer, but it also has a return value. They sound quite different (one is a variable, one is a language construct), but they are used for the same purpose here. Half the time you return, half the time you set result, and this leads to your code having the effects you are observing.
The solution is to pick a side. Either use only result - update the method to have a void return value, and do not use the return x; statement (only return;). Alternatively, get rid of result entirely, and communicate using return.
if(i==1){
return 0;
}
Take this line and compare to the very next one:
factorial(i-1);
This line calls the factorial function and throws out whatever it returned because you don't assign it anywhere. That is why you can't observe that 0 you are returning: Because you ignore it.
It looks to me like you think that return 0; somehow sets result, or that result holds 'whatever the function returned' but this isn't true. They are separate things.
public static void reversePrint(int[] numbers){
if(numbers.length == 0) //Base case
return;
int[] a = new int[numbers.length-1];
for(int i = 0; i < numbers.length-1;i++)
a[i] = numbers[i+1];
reversePrint(a);
System.out.println(numbers[0]);
}
public static void main(String[] args){
int[] array = new int[]{5,1,34,12,7};
reversePrint(array);
}
Output:
7
12
34
1
5
Everything is pretty straightforward, have a function called reversePrint. When you pass those numbers to the function reversePrint, it takes the first value out, (in this case '5') and then it calls reversePrint again,now with the smaller list.
This Continues until finally we're left with no more numbers, and begins to print them out.
My confusion is in line '10', if the list of numbers is getting less and less by removing the first number each time, how does calling 'System.out.println(numbers[0]);' retrieve numbers that have been removed from the list, and doing so in reverse order?
Here's a scheme to understand the stack of calls in this recursion:
reversePrint([5,1,34,12,7]) {
reversePrint([1,34,12,7]) { // <-- this list IS A COPY, it just ignores the first number
reversePrint([34,12,7]) {
reversePrint([12,7]) {
reversePrint([7]) {
reversePrint([]);
print(7); // <-- this is the first number of the current list
};
print(12);
};
print(34);
};
print(1);
};
print(5);
};
As you can see, the System.out.println(numbers[0]) is called AFTER propagating the recursion. Note that a new array is created in each call, you don't lose the first number.
First, you don't actually remove numbers: you copy them from numbers to a skipping the one in position 0. That System.out.println prints from numbers, so the integer at index 0 will still be the same.
Second, the System.out.println statement is after the recursive call, so it will be executed after that call returns. So basically, the first System.out.println that will execute will be the one in the last call:
for ...
reversePrint
|
| for ...
| reversePrint
| |
| | for ...
| | reversePrint
| | |
| | | for ...
| | | reversePrint
| | | |
| | | | for ...
| | | | reversePrint
| | | | |
| | | | | return
| | | | |
| | | | System.out.println
| | | |
| | | System.out.println
| | |
| | System.out.println
| |
| System.out.println
|
System.out.println
That's an exceptionally ineffective implementation of
Arrays.asList(5, 1, 34, 12, 7).reverse().forEach(System.out::println)
But to answer your question, the reversePrint creates a new array with the first item removed from the array, then prints out the first of the original. The second call will receive [1, 34, 12, 7] because the first has removed the 5, so it will print out the 1.
how does calling 'System.out.println(numbers[0]);' retrieve numbers that have been removed from the list, and doing so in reverse order?
No numbers have been removed from any array in this code. Each recursive call creates a new array and copies to it all the elements of the current array except of the first element.
Therefore the array passed to the i'th call to reversePrint() contains the last n-i+1 elements of the original array.
The recursion ends when reversePrint() is called for an empty array. When the last recursive call returns, the next to last call prints numbers[0], which contains the last element of the original array. Then the previous reversePrint() prints numbers[0], which contains the next to last element of the original array, and so on...
These are the recursive calls:
reversePrint({5,1,34,12,7})
reversePrint({1,34,12,7})
reversePrint({34,12,7})
reversePrint({12,7})
reversePrint({7})
reversePrint({})
Now, after each of them returns, numbers[0] is printed, so you get
7
12
34
1
5
Perhaps doing it the classic way (rather than making a copy of the array as you do) it would be clearer what is happening.
// Private version to pass the offset which increases on each call.
private static void reversePrint(int[] numbers, int from){
// Base case - stop at end of array.
if(numbers.length > from) {
// Print everything else first.
reversePrint(numbers, from+1);
// Then the one I am at.
System.out.println(numbers[from]);
}
}
public static void reversePrint(int[] numbers){
reversePrint(numbers, 0);
}
public void test() throws Exception {
System.out.println("Hello world!");
int[] array = new int[]{5,1,34,12,7};
reversePrint(array);
}
I am finding a solution to pass each scenario outline example row as object in cucuber-jvm.
So as for example if I consider a scenario
Scenario Outline: example
Given I have a url
When I choose <input_1>
Then page should hold field1 value as <validation field1> field2 value as <validation field2> fieldn value as <validation fieldn>
Examples:
| input_1 | validation field1 |validation field2|validation field n|
| input_1_case_1 | expected value 1 |expected value 1 |expected value n |
So in Step file
public void validationMethod(String validation field2,String validation field2,String validation field3){
............
............
}
So if I have more field then my method also consume more argument.
Now I want to pass all validation field as object in method. So is it possible using cucumber jvm? If possible could any one can please provide some suggestion with sample code.
You could try something like this
Then Use the following values
| <validation field1> | <validation field2> | <validation field3> |
Examples:
| input_1 | validation field1 |validation field2|validation field3 |
| input_1_case_1 | expected value 1 |expected value 2 |expected value 3 |
| input_2_case_2 | expected value 1 |expected value 2 |expected value 3 |
Step Definition
#Then("^Use the following values$")
public void useFollVal(List<String> valFields) {
//The values will be inside the list. Use index to access
}
You can even get an validation object instead of string list ie List<ValidationData>. To do this add a header in the step (not the examples table) with names matching the variables in the ValidationData class and cucumber will populate the data into the object.
Then Use the following values
| valField1 | valField2 | valField3 | <<<--- Header to add
| <validation field1> | <validation field2> | <validation field3> |
valField1 -> private String valField1; in ValidationData
Step Definition
#Then("^Use the following values$")
public void useFollVal(List<ValidationData> valObject) {
}
This is more of a comment: Wouldnt a variable length argument list work for you? You would need to know the sequence of your params though, without the argument names to help out.
public void multiParams(String... val){
}
1 public class TestWin{
2 public static void main(String[] args){
3 int n;
4 hexagon[][] board;
5
6 n = 4;
7 board = new hexagon[n][n];
8 board[0][0].value = 'R';
Hi. javac doesn't like what I did on line 8. Does anyone know why?
It's been a while since I've so much as looked at Java, but have you tried doing this first?
board[0][0] = new hexagon(); // or whatever its constructor is
Spot on kwatford. All you have done with line 7 is to tell java to create space for n*n Hexagon objects in a 2 dimensional array.
You will still need to call new for each of these Hexagons
Essentially, you need to replace line 7 with something like:
board = new Hexagon[n][n];
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
board[i][j] = new Hexagon();
Short Answer:
As kwatford said what you need to do is this:
board[0][0] = new hexagon(); // or whatever its constructor is
Longer Explanation:
Just to expand further. Your 2D array is; an array of pointers (or references in Java). This is what one row of the array will look like immediately after this call board = new hexagon[n][n];:
0 1 2 3 4 5 // column index, row index = 0
-------------------------------------------
| | | | | | | | | | // value
--- | ----- | ----- | ---------------------
| | | ...
| | |
| | |
| | |
| | v
| | Null
| v
| Null
v
Null (This means that it points to nothing)
You tried:
board[0][0].value = 'R';
which is the same as this:
null.value = 'R';
You have initialized your array using this line:
board = new Hexagon[n][n];
But you still need to initialize the elements in your array. This would initialize the first three:
board[0][0] = new hexagon(); // or whatever its constructor is
board[1][0] = new hexagon(); // or whatever its constructor is
board[2][0] = new hexagon(); // or whatever its constructor is
Which would result in an array that looks like this:
0 1 2 3 4 5 // column index, row index = 0
-------------------------------------------
| | | | | | | | | | // value
--- | ----- | ----- | ---------------------
| | |
| | |
| | |
| | |
| | v
| | An instance of type Hexigoon (what you get when you type new Hexigon)
| v
| An instance of type Hexigon (what you get when you type new Hexigon)
v
An instance of type Hexigon (what you get when you type new Hexigon)
I remember banging my head on the table with this exact problem two years ago. I love stackoverflow
To expand on what kwatford said, initializing an array in java gives you nulls if the array type is an object. If you had a raw array, such as an array of doubles, you would start with 0 as the entry for each element of the array.
I have a two command "add" and "undo". With "add" operation, more than one, including one, pair can be sent to the program. On the other hand, with "undo" operation, last sent data should be given back. To implement this functionality, I have thought;
I should have these elements of data structure;
| | HashMap<String, String> : It is used for storing data
| |
| |
| |
--------
Stack : It seems best to "undo" and "add" operations.
At some point, I should, in practice, have below stack;
| |
| |
| ________________________________ |
| | (filename5, date1) | | third HashMap type container
| | (filename6, date5) | | holding three items
| | (filename7, date9) | |
| |______________________________| |
| |
| ________________________________ | second HashMap type container
| | (filename3, date2) | | holding one item
| |______________________________| |
| |
| ________________________________ | first HashMap type container
| | (filename1, date1) | | holding two items
| | (filename2, date2) | |
| |______________________________| |
|----------------------------------|
My question is "How can I ensure first keys in all containers are unique in the whole stack?"
If it is not possible with above data structures, what should I use as a data structure to implement mentioned wish?
Why not just keeping two structures: Stack<String> and check, whether it contains or not filename_x, and second structure - your hashmap HashMap<String, String>?
UPD: In other words, you do not need to hold theese maps inside stack as its elements.
It is solved with three Java Stack, and own stack implementation to make push and pop operations synhronized. Implementation is ;
class OwnStack{
private final Stack<String> file = new Stack<String>()
private final Stack<String> date = new Stack<String>()
private final Stack<String> numberOfElementsPushedAtTheSamTime
= new Stack<String>()
public void push(String []files, String []date{
/* Algorithm
* Iterate over files
* if file is in stack
* donot push anything to stack
* else
* push file to stack
* push category to stack
* push number of entries pushed at the same time to stack (files.length())
*/
}
public void pop(){
/*
* Algorithm
* If size is zero in file stack
* do nothing
* else
* get top number from numberOfElementsPushedAtTheSamTime stack
* iterate over stacks returned number times
* pop files stack
* pop date stack
*/
// I donot need return values
}
}