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;
}