1. Modifying arrays sent as parameters
2. Returning arrays from methods
1. Modifying arrays sent as parameters
The purpose of this example is to illustrate that a method can modifiy the contents
of an array sent in as a parameter. The effect (the modification) will be observed
outside of the method.
Example: Write a method scaleElements( numbers, factor ) which takes as input an array
of numbers and a factor an modifies the input array by overwriting the contents
of each cell by multiplying its value by the given factor.
For example,
double[] testArray = {5, 2, 8 , 1};
scaleElements(testArray, 4);
printArray(testArray); // displays 20 8 32 4 -- the given array
// has been modified
Note that this is an error:
double[] result = scaleElements(testArray, 4);
since this version of the method is void, i.e. it does not return anything.
The method works by traversing the array, multiplying the contents of the current
cell by the factor and storing the result back in the cell (i.e. overwriting the cell).
void scaleElements( double[] numbers, double factor )
{
for (int i = 0; i < numbers.length; i = i + 1)
{
numbers[i] = factor*numbers[i]; // OR: double curValue = numbers[i];
} // numbers[i] = factor*curValue;
}
2. Returning arrays from methods
We also looked at a slightly different version of the previous method. Here the goal
is to leave the input array intact and instead return a brand new array which contains
the original elements scaled by the given factor.
Example: Write a method scaleElements(numbers, factor) which takes as input an array
of numbers and a factor an returns a brand new array that contains the original
elements multiplied by the given factor.
For example,
double[] testArray = { 5, 2, 8 , 1 };
double[] resultArray = scaleElements( testArray, 4 );
printArray(testArray); // displays 5, 2, 8, 1 -- the given array
// has NOT been modified
printArray(resultArray); // displays 20, 8, 32, 4 -- the result array
// has the scaled values
The only difference with the previous version is that this time, instead of storing each
scaled value back in the given array, we need to store it in a different array. This means
that before we begin the traversal we need to create a new array that is the same size as
the input array.
Here is the code for the second version of scaleElemenst:
double[] scaleElements( double[] numbers, double factor )
{
double[] result = new double[ numbers.length ];
for ( int index = 0 ; index < numbers.length ; index = index + 1 )
{
result[ index ] = factor*numbers[ index ];
}
return result;
}
Notice the differences:
- return type is int[] -- we are returning an array
- we first create a new array that is the same size as the input array
- we need to return the result array (nothing was returned in previous version)
Duplicating the elements in an array
Example: Write a method repeatElements(numbers) which takes as input an array
of numbers and returns a brand new array which contains the original elements
repeated twice.
For example,
// one-line test
printArray( new double[]{ 5, 9, 6, 7 } ); // displays 5 9 6 7 5 9 6 7
// multi-line test
double[] testArray = { 5, 9, 6, 7 };
double[] repeated = repeatElements(testArray);
printArray(repeated); // displays 5 9 6 7 5 9 6 7
The problem can be solved by creating a new array which is twice as big as the given
array and traversing the given array one element at a time to copy its elements.
During the traversal we make sure that the current element is placed in the correct
cells in the result array.
It is helpful to keep track of two separate indices that indicate where each element
should be placed during each cycle of the loop.
i
|...
_V_____________
input array: |_5_|_9_|_6_|_7_|
0 1 2 3
j k
|... |...
_V_______________V_____________
result array: |___|___|___|___|___|___|___|___|
0 1 2 3 4 5 6 7
index j starts at 0
index k starts at however many elements are in the input array
Here is the outline of the method:
1. Create a result array that is twice the size of the original
2. Create two index variables, j and k, that indicate where to put the current element
3. Traverse the input array one element at a time:
4. Place the current element in the result array
at the locations specified by j and k
5. Advance j and k by 1 for next cycle
5. Return the result array.
double[] repeatElements( double[] numbers )
{
double[] result = new double[ 2*numbers.length ]; // create array that is twice as big
int j = 0; // should point to first empty slot
int k = numbers.length; // should point to first empty slot of next section (skip one length)
for ( int i = 0 ; i < numbers.length ; i = i + 1 )
{
result[ j ] = numbers[ i ]; // copy once
result[ k ] = numbers[ i ]; // copy again
j = j + 1; // get ready for next cycle
k = k + 1; // get ready for next cycle
}
return result;
}
Second version
This method can be written by keeping track only of index j -- index k can be
computed from index j, since they are always a whole length apart.
double[] repeatElements( double[] numbers )
{
double[] result = new double[ 2*numbers.length ];
int j = 0;
for ( int i = 0; i < numbers.length; i = i + 1 )
{
int k = j + numbers.length; // j and k are one length apart
result[ j ] = numbers[ i ];
result[ k ] = numbers[ i ];
j = j + 1; // only one index to worry about
}
return result;
}
Third version
The final version uses the observation that the values of i and j always
match - they both start at 0 and increase by 1 -- so j is not needed.
double[] repeatElements( double[] numbers )
{
double[] result = new double[ 2*numbers.length ];
for ( int i = 0; i < numbers.length; i = i + 1 )
{
int k = i + numbers.length; // i (which is same as j) and k are one length apart
result[ i ] = numbers[ i ];
result[ k ] = numbers[ i ];
// no indices to worry about
}
return result;
}