Array algorithms for working with multiple arrays
Lesson content
- What working with multiple arrays means
- Creating a new array as a copy of an existing array
- Copying elements from one array into another existing array
- Merging two arrays into a new array by appending one to the other
- Merging two arrays into a new array without duplicate values
- Comparing two arrays for equality
- Most common errors
What working with multiple arrays means
In previous lessons, algorithms for working with a single array were covered. However, it’s often necessary to work with multiple arrays at the same time, which is why there are corresponding algorithms.
Common operations when working with multiple arrays typically involve:
- Creating a new array based on one or more existing arrays, or
- Comparing two arrays for equality.
In most cases, this involves copying some or all elements of an existing array, or merging two arrays into a new one. Specifically:
- Creating a new array as a copy of an existing array
- Copying elements from one array into another existing array
- Merging two arrays into a new array by appending one to the other
- Merging two arrays into a new array without duplicate values
- Merging two arrays into a new array based on a specific condition (not all elements are copied)
- Comparing two arrays for equality
These algorithms can be fairly complex and may involve multiple FOR loops and nested IF statements (especially if some element selection is required). In some situations, a FOR-EACH loop may also be used for part of the algorithm.
Other common characteristics of these algorithms:
- A new array is usually created, and its elements are modified.
- One or more existing arrays serve as the basis.
- They often include multiple loops, which may or may not be nested, since multiple arrays must be processed.
- It’s common to introduce helper methods and/or reuse existing methods to make the overall code shorter and/or more readable.
Creating a new array as a copy of an existing array
As the title suggests, the idea is to create a copy of an existing array — a completely new array. In the simplest case, we make a full copy of the array, meaning all of its elements are copied without exceptions. After copying, the order of elements in the new array is the same as in the original one.
In practice, this means:
- Initializing a new array with the same capacity as the existing array.
- Copying each element from the existing array to the new array one by one.
Example 1
Create a class MonthlyProfits that includes:
- An attribute profits which represents an array of 12 real numbers. Each element represents the profit for a specific month (January, February, …, December).
- A constructor that takes an array of 12 monthly profits as a parameter and copies the elements of that array into the profits attribute.
- A method enterProfit that takes a real number (profit) and an integer (month number: 1 for January, 2 for February, …, 12 for December) as parameters, and stores the profit for the corresponding month in the array.
- A method print that prints all monthly profits to the screen.
Create a class TestMonthlyProfits which, in the main method, creates an object of the MonthlyProfits class by passing in the following array of 12 monthly profits: {0, 122.33, 200.1, 0, 255.44, 878.5, 543.0, 0, 0, 0, 449.7, 100.8} and prints all monthly profits to the screen.
1 class MonthlyProfits {
2
3 double[] profits;
4
5 MonthlyProfits(double[] monthlyProfits){
6 // The profits array is first initialized with
7 // the same capacity as the entered array (its length)
8 profits = new double[monthlyProfits.length];
9
10 // Copying elements one by one
11 for (int i = 0; i < monthlyProfits.length; i++)
12 profits[i] = monthlyProfits[i];
13 }
14
15 void enterProfit(double profit, int month){
16 profits[month -1] = profit;
17 }
18
19 void print(){
20 for(int i = 0; i < profits.length; i++)
21 System.out.println(profits[i]);
22 }
23 }
1 class TestMonthlyProfits {
2
3 public static void main(String[] args) {
4 double[] monthlyProfits =
5 {0, 122.33, 200.1, 0, 255.44, 878.5, 543.0, 0, 0, 0, 449.7, 100.8};
6
7 MonthlyProfits mp = new MonthlyProfits(monthlyProfits);
8
9 mp.print();
10 }
11 }
The array copy algorithm is actually implemented in the constructor of the MonthlyProfits class. The first step is to create a new array with the same capacity as the existing array, so that all elements fit (profits = new double[monthlyProfits.length];). In the second step, a FOR loop iterates through the existing array monthlyProfits and copies each of its elements into the new array at the same index. Because the index is the same, the loop counter i is used for accessing both arrays (profits[i] = monthlyProfits[i]).
It is important to note: if you simply assign the array reference from one variable to another, you do not get a new array. For example:
1 MonthlyProfits(double[] monthlyProfits){
2 profits = monthlyProfits;
3 }
This is not copying — both variables (profits and monthlyProfits) will point to the same array in memory (like having two remotes for one TV), so no new array is created.
If you are using an element counter (like counter), the copying algorithm remains the same, but you must also set the counter of the new array to match that of the original. This is needed to know how many spots are filled in the new array, so new values can be added starting at the first available spot.
Often, you may want to copy only selected elements, so you don’t copy all elements from the original array, but only those that meet a specific condition (e.g., only values greater than 0). Still, the array should be initialized with the same capacity as the original, since all elements might meet the condition.
Example 2
Create a class FinancialCoefficients that includes:
- An attribute coefficients representing an array of coefficients (e.g., 1.02).
- An attribute counter representing the number of values actually entered into the array. Initial value is zero.
- A constructor that initializes the coefficients array with the capacity passed as a parameter.
- A constructor that takes a new array of coefficients (array of real numbers) and the counter value for that array. It initializes the coefficients attribute and copies into it only the values greater than zero.
- A method enterCoefficient that takes a real number as a parameter and adds it to the array at the first free position. If there’s no space in the array, it simply prints “ERROR”.
- A method print that prints all entered coefficients to the screen.
Create a class TestFinancialCoefficients that, in the main method, creates an object of FinancialCoefficients by passing the array {1.1, -0.5, 0.8, -0.2, 0, 0} and a counter with value 4, and then prints all coefficients to the screen.
1 class FinancialCoefficients {
2
3 double[] coefficients;
4 int counter = 0;
5
6 FinancialCoefficients(int capacity){
7 coefficients = new double[capacity];
8 }
9
10 FinancialCoefficients(double[] coefficientsNew, int counterNew){
11 // The coefficients array is first initialized
12 // to the same capacity as the entered array
13 coefficients = new double[coefficientsNew.length];
14
15 // Only elements which are larger than
16 // zero are copied.
17 for (int i = 0; i < counterNew; i++)
18 if (coefficientsNew[i] > 0){
19 coefficients[counter] = coefficientsNew[i];
20 counter++;
21 }
22
23 // Alternatively, this can be
24 // written more simple by calling
25 // the method enterCoefficient
26 /*for (int i = 0; i < counterNew; i++)
27 if (coefficientsNew[i] > 0)
28 enterCoefficient(coefficientsNew[i]);
29 */
30 }
31
32 void enterCoefficient(double newCoefficient){
33 if (counter < coefficients.length){
34 coefficients[counter] = newCoefficient;
35 counter++;
36 }
37 else System.out.println("ERROR");
38 }
39
40 void print(){
41 for(int i = 0; i < counter; i++)
42 System.out.println(coefficients[i]);
43 }
44 }
1 class TestFinancialCoefficients {
2
3 public static void main(String[] args) {
4 double[] coefficientsNew =
5 {1.1, -0.5, 0.8, -0.2, 0, 0};
6
7 FinancialCoefficients fc =
8 new FinancialCoefficients(coefficientsNew,4);
9
10 fc.print();
11 }
12 }
The copy algorithm is implemented in the constructor with two parameters. Since the example uses an element counter, the method must receive both the array and its counter. That way, not the entire array is copied, but only the entered elements (from 0 to newCounter - 1), and only those greater than zero.
The algorithm begins by initializing the array (coefficients) to the same capacity as the input array (coefficients = new double[coefficientsNew.length]) because it’s possible that all values are positive and should be copied.
Then, each element is checked (if greater than zero), and copied one by one. The copying is done in the same way as adding a new value — to the position indicated by the current value of the counter (counter), and then the counter is incremented.
There’s no need to check if there’s room left, because both arrays have the same capacity.
Since the copying code is the same as the code for adding a new element, you can simplify the logic by simply calling the existing enterCoefficient method. This version is written in comments in the same constructor, and is considered a better solution — not only is it shorter, but it avoids repeating the same code in two places.
Copying elements from one array into another existing array
The problem solved by this algorithm is very similar to the previous problem of creating a copy of an existing array (or part of it), but with four significant differences:
- No new array is created. Both arrays already exist.
- The arrays being used do not have to be of the same capacity.
- The array into which elements are copied does not have to be empty.
- It may happen that not all elements can “fit” because the capacity has been filled.
Example 3
Create a class ExamGrades which has:
- An attribute grade representing the grades of students for that exam. The grade is an integer in the range of 5 to 10.
- An attribute counter representing the current number of entered grades in the array. Its initial value is 0.
- A constructor that receives the number of students who registered for the exam in that session as a parameter and initializes the capacity of the grades array to that number.
- A method enterGrade which receives a grade as a parameter, enters it into the array at the first available position, but only if the grade is in the range from 5 to 10 and if there is space in the array. Otherwise, the method just prints “ERROR” on the screen.
- A method enterGrades which receives an array of student grades as a parameter and copies (adds) them into the already existing grads array, but only if the grades are within the range of 5 to 10. If some grades are already in the array, they remain. If not all new grades can be copied into the array, as many as possible will be added up to the full capacity of the array.
- A method print which prints all the grades on the screen.
Create a class TestExamGrades that in the main method creates an object of the ExamGrades class with 12 students registered and:
- Enters individual grades 5, 10, 10, 7, and 8.
- Enters two grades at once, 6 and 9.
- Prints all grades on the screen.
1 class ExamGrades {
2
3 int[] grades;
4 int counter = 0;
5
6 ExamGrades(int numberOfStudents){
7 grades = new int[numberOfStudents];
8 }
9
10 void enterGrade(int newGrade){
11 if (newGrade >= 5 && newGrade <= 10 && counter < grades.length) {
12 grades[counter] = newGrade;
13 counter++;
14 }
15 else System.out.println("ERROR");
16 }
17
18 void enterGrades(int[] newGrades){
19 // Here we call the enterGrade method to
20 // do a part of the work (enter ONE grade
21 // from the newGrades array) and in order not to
22 // repeat its code.
23 for (int i = 0; i < newGrades.length; i++)
24 enterGrade(newGrades[i]);
25
26 // Alternatively, if we do not call the
27 // enterGrade method, we must repeat its
28 // code in the for loop
29 /*for (int i = 0; i < newGrades.length; i++)
30 if (newGrades[i] >= 5 && newGrades[i] <= 10 && counter < grades.length) {
31 grades[counter] = newGrades[i];
32 counter++;
33 }
34 else System.out.println("ERROR");*/
35 }
36
37 void print(){
38 for(int i = 0; i< counter; i++)
39 System.out.println(grades[i]);
40 }
41
42 }
1 class TestExamGrades {
2
3 public static void main(String[] args) {
4 ExamGrades eg = new ExamGrades(12);
5
6 eg.enterGrade(5);
7 eg.enterGrade(10);
8 eg.enterGrade(10);
9 eg.enterGrade(7);
10 eg.enterGrade(8);
11
12 int[] newGrades = {6, 9};
13
14 eg.enterGrades(newGrades);
15
16 eg.print();
17 }
18 }
The algorithm for copying some elements of an array into an existing array is given in the enterGrades method. The new grades are provided in an array that is passed as a parameter to the method. It is important to note that no initialization is done because both arrays are already initialized. In fact, at the moment when this method gets called from the main method, neither of the two arrays is empty — they already contain some grades.
*The algorithm actually uses a FOR loop to go through the elements of the newGrades array and copy them one by one into the grades array. Since before adding, it is necessary to check if the grade is in the range from 5 to 10 and if there is space in the grades array, the enterGrade method is called within the FOR loop, which does this check. In principle, this is code reuse, and besides avoiding repeating code, it simplifies the look of the algorithm by delegating part of the task to another method. An alternative solution without calling the enterGrade method is provided in the comments.
Merging two arrays into a new array by appending one to the other
The problem of merging two arrays into a new array by appending can be seen as copying the first array, and then the second array, into the new array. In the simplest case, all elements of both arrays are transferred to the new array, and the order is such that the new array first contains all the elements of one array, and then all elements of the second array.
For example, if the following two arrays are given:
1 {1, 2, 3, 4}
2 {10, 11, 12}
Appending the second array to the end of the first array results in the following new array:
1 {1, 2, 3, 4, 10, 11, 12}
Alternatively, if the first array is appended to the end of the second array (the second order), the new array will look like this:
1 {10, 11, 12, 1, 2, 3, 4}
From an algorithmic perspective, the following steps are required:
- Initialize the new array with a capacity equal to the sum of the capacities of the two arrays.
- Copy (add) the elements of the first array into the new array starting from the beginning.
- Copy (add) the elements of the second array into the new array starting from the position of the last copied element of the first array.
If it is necessary for the new array to first contain the elements of the second array, and then the first array, simply swap the order of steps 2 and 3 so that the elements of the second array are entered first, and then the elements of the first array.
Example 4
Create a class FinancialCoefficients2 which has:
- An attribute coefficients representing an array of coefficients (e.g., 1.02).
- An attribute counter representing the actual number of values entered into the array. Its initial value is zero.
- A constructor that receives two arrays of coefficients (two arrays of real numbers) and two counters for the elements of these arrays as parameters. The constructor initializes the coefficients attribute and copies all the elements of both arrays into the coefficients array.
- A method enterCoefficient which takes a real number representing a coefficient and enters that value into the array at the first available position. If there is no space in the array, it just prints the message “ERROR” on the screen.
- A method print which prints all the entered coefficients on the screen.
Create a class TestFinancialCoefficients2 that in the main method creates an object of the FinancialCoefficients2 class by entering two arrays of coefficients:
- {1.1, -0.5, 0.8, -0.2, 0, 0} with a counter value of 4.
- {14.1, 12.2, 0} with a counter value of 2.
- Then, enter one more coefficient 13.3 and print all the coefficients on the screen.
1 class FinancialCoefficients2 {
2
3 double[] coefficients;
4 int counter = 0;
5
6 FinancialCoefficients2(double[] coefficientsNew, int counterNew,
7 double[] coefficientsNew2, int counterNew2){
8 // The coefficients array is first initialized
9 // to the capacity equal to the sum of capacities
10 // of two entered arrays.
11 coefficients = new double[coefficientsNew.length + coefficientsNew2.length];
12
13 // Copying the elements of the first entered
14 // array into the coefficients array.
15 for (int i = 0; i < counterNew; i++)
16 enterCoefficient(coefficientsNew[i]);
17
18 // Then, copying the elements of the second entered
19 // array into the coefficients array.
20 for (int i = 0; i < counterNew2; i++)
21 enterCoefficient(coefficientsNew2[i]);
22 }
23
24 void enterCoefficient(double newCoefficient){
25 if (counter < coefficients.length){
26 coefficients[counter] = newCoefficient;
27 counter++;
28 }
29 else System.out.println("ERROR");
30 }
31
32 void print(){
33 for(int i = 0; i < counter; i++)
34 System.out.println(coefficients[i]);
35 }
36 }
1 class TestFinancialCoefficients2 {
2
3 public static void main(String[] args) {
4 double[] coefficientsNew =
5 {1.1, -0.5, 0.8, -0.2, 0, 0};
6
7 double[] coefficientsNew2 =
8 {14.1, 12.2, 0};
9
10 FinancialCoefficients2 fc =
11 new FinancialCoefficients2(
12 coefficientsNew,4,
13 coefficientsNew2, 2);
14
15 fc.enterCoefficient(13.3);
16
17 fc.print();
18 }
19 }
In the constructor of the FinancialCoefficients2 class, the algorithm for merging two arrays into a new array is shown. The first step is the initialization of the new array (in this case, the coefficients attribute) with a capacity equal to the sum of the lengths (capacities) of the two input arrays. This is necessary to ensure that all elements of the two arrays will fit into the new array.
After that, all elements of the first input array are entered into the coefficients array. Since the enterCoefficient method is called, the elements will be added sequentially from the beginning of the new array. The FOR loop iterates up to counterNew - 1 to only copy the actually entered values. If the counter was not used, the FOR loop would go up to length - 1.
Then, the entire procedure is repeated, but for the second input array. The elements of this second array will be added to the new array after the elements of the first array, i.e., they will be appended to them.
In cases of merging arrays, there are also slightly more complex situations where not all elements are copied, but only some that meet specific criteria. From an algorithmic perspective, the only difference is that a nested IF statement will be introduced within the FOR loop to check the criteria before copying.
Example 5
Suppose in the class FinancialCoefficients2 from the previous example, the task is to modify the constructor so that it only transfers positive coefficients into the coefficints array, just like before.
In that case, the constructor would look like this:
1 FinancialCoefficients2(double[] coefficientsNew, int counterNew,
2 double[] coefficientsNew2, int counterNew2){
3 coefficients = new double[coefficientsNew.length + coefficientsNew2.length];
4
5 for (int i = 0; i < counterNew; i++)
6 if (coefficientsNew[i] > 0)
7 enterCoefficient(coefficientsNew[i]);
8
9 for (int i = 0; i < counterNew2; i++)
10 if (coefficientsNew2[i] > 0)
11 enterCoefficient(coefficientsNew2[i]);
12 }
The only difference is the introduction of an IF statement (in both FOR loops) that checks if the coefficient is greater than zero.
Example 6
If, in the class FinancialCoefficients2 from Example 5, we do not use element counters, and both input arrays are filled to the maximum (no empty spaces), then the merging of arrays can be done without auxiliary methods and without calling existing methods. In this case, the constructor would look like this:
1 FinancialCoefficients2(double[] coefficientsNew,
2 double[] coefficientsNew2){
3 coefficients = new double[coefficientsNew.length + coefficientsNew2.length];
4
5 // First, copy the elements from the first input array
6 // into the coefficients array, starting from the beginning.
7 for (int i = 0; i < coefficientsNew.length; i++)
8 coefficients[i] = coefficientsNew[i];
9
10 // Then, copy the elements from the second input array,
11 // starting after the last copied element of the first array.
12 for (int i = 0; i < coefficientsNew2.length; i++)
13 coefficients[coefficientsNew.length + i] = coefficientsNew2[i];
14 }
It is important to notice that the elements of the first array are inserted into the coefficients array from the beginning, i.e., from index 0 to coefficientsNew.length - 1, as that is the index of the last element of the first input array.
However, the elements of the second array coefficientsNew2 are inserted after that, i.e., from index coefficientsNew.length to coefficientsNew.length + coefficientsNew2.length - 1 (the end of the coefficients array). This is done by having the second FOR loop counter (i) go from 0 to coefficientsNew2.length - 1 (to loop through all the elements of the second input array), and inserting them into the coefficients array at position [coefficientsNew.length + i], effectively shifting the position by the length of the first array, and placing them after the elements of the first array that were already inserted.
Merging two arrays into a new array without duplicate values
In some cases, it is necessary to ensure that no values in the array repeat (i.e., there are no duplicate values). This is not particularly common, and other data structures (such as sets or maps which do not allow duplicates) are usually used for this purpose, but it is also possible to achieve something similar with arrays.
The algorithm is similar to the previous one that merges two arrays, but before copying each element, a check is performed to see if the element already exists in the array. If it does, it is not inserted again, avoiding the appearance of duplicates. Typically, a helper method is introduced to check if the value we want to add already exists in the array.
Example 7
Create a class FinancialCoefficients3 that has:
- An attribute coefficients which represents an array of coefficients (e.g., 1.02).
- An attribute counter which represents the number of actual values entered into the array. The initial value is zero.
- A constructor that takes as parameters two arrays of coefficients (two arrays of real numbers) and two counters for the elements of those arrays. The constructor initializes the attribute (array) coefficients and copies the elements from both input arrays into the coefficients array, ensuring that there are no duplicate values.
- A method enterCoefficient that takes a real number representing a coefficient and inserts that value into the array at the first available position. If there is no space, it simply prints the message “ERROR” on the screen.
- *A method print that prints all the entered coefficients on the
- screen.*
Create a class TestFinancialCoefficients3 which in the main method creates an object of the FinancialCoefficients3 class by inserting two arrays of coefficients into it, and then prints all the coefficients:
- {1.1, -0.2, 0.8, -0.2, 0, 0} and a counter with a value of 4.
- {1.1, 12.2, 0.8, 0} and a counter with a value of 3.
1 class FinancialCoefficients3 {
2
3 double[] coefficients;
4 int counter = 0;
5
6 FinancialCoefficients3(double[] coefficientsNew, int counterNew,
7 double[] coefficientsNew2, int counterNew2){
8 coefficients = new double[coefficientsNew.length + coefficientsNew2.length];
9
10 // The elements from the first entered array are
11 // copied into the coefficients array, but it
12 // is checked if they already exist in the
13 // coefficients array. If they do not exist,
14 // they are copied.
15 for (int i = 0; i < counterNew; i++)
16 if (exists(coefficientsNew[i]) == false)
17 enterCoefficient(coefficientsNew[i]);
18
19 // Then, the elements from the second entered array are
20 // copied into the coefficients array, but it
21 // is checked if they already exist in the
22 // coefficients array. If they do not exist,
23 // they are copied.
24 for (int i = 0; i < counterNew2; i++)
25 if (exists(coefficientsNew2[i]) == false)
26 enterCoefficient(coefficientsNew2[i]);
27 }
28
29 boolean exists(double coefficient){
30 for (int i = 0; i < counter; i++)
31 if (coefficients[i] == coefficient)
32 return true;
33
34 return false;
35 }
36
37 void enterCoefficient(double newCoefficient){
38 if (counter < coefficients.length){
39 coefficients[counter] = newCoefficient;
40 counter++;
41 }
42 else System.out.println("ERROR");
43 }
44
45 void print(){
46 for(int i = 0; i < counter; i++)
47 System.out.println(coefficients[i]);
48 }
49 }
1 class TestFinancialCoefficients3 {
2
3 public static void main(String[] args) {
4 double[] coefficientsNew =
5 {1.1, -0.2, 0.8, -0.2, 0, 0};
6
7 double[] coefficientsNew2 =
8 {1.1, 12.2, 0.8, 0};
9
10 FinancialCoefficients3 fk =
11 new FinancialCoefficients3(
12 coefficientsNew,4,
13 coefficientsNew2, 3);
14
15 fk.enterCoefficient(13.3);
16
17 //Note that there are no duplicates for the coefficients 1.1, 0.2 and 0.8
18 fk.print();
19 }
20 }
First, it is important to note that in the class FinancialCoefficients3, a helper method exists is introduced which checks whether the coefficient that is being inserted as a parameter already exists in the array (the method returns true) or not (the method returns false). This method is not mentioned in the task description, but it is introduced to avoid repeating the duplicate-checking code in two places inside the constructor (once during the insertion of the first array, and then when inserting the second array). Another reason for this is that it makes the constructor appear simpler, i.e., the algorithm is more readable.
The algorithm for merging two arrays without duplicates is given in the constructor - as in previous examples. First, the coefficients array is initialized with a capacity equal to the sum of the lengths (capacities) of both input arrays. Then, the elements of the first array are copied, followed by those of the second array. Before copying each element, it is checked whether that element already exists in the array by calling the exists method. If it does not exist (if the method returns false), then it is inserted into the array. If it exists, it is not inserted into the array.
As already mentioned, the common practice is to introduce new helper methods or call existing methods from the class (from another method or constructor) in order to:
- Avoid repeating code (the code is shorter and easier to modify later since changes are made in one place).
- Write more readable code (instead of, for example, duplicate loops, single loops are written, each in its own method).
In the following example, you can see how the constructor from the previous example would look if no helper methods were introduced and no existing methods were called to handle part of the work.
Example 8
Look at the constructor of the class FinancialCoefficients3 from the previous example.
In the case where we don’t use the helper method exists, we must include all the code for checking duplicates directly in the constructor. This would result in a nested FOR loop, and the code would look like this:
1 FinancialCoefficients3(double[] cofficientsNew, int counterNew,
2 double[] cofficientsNew2, int counterNew2){
3 cofficients = new double[cofficientsNew.length + cofficientsNew2.length];
4
5 for (int i = 0; i < counterNew; i++){
6 boolean exists = false;
7
8 for (int j = 0; j < counter; j++)
9 if (cofficients[j] == cofficientsNew[i]){
10 exists = true;
11 break;
12 }
13
14 if (!exists)
15 enterCoefficient(cofficientsNew[i]);
16 }
17
18 for (int i = 0; i < couterNew2; i++){
19 boolean exists = false;
20
21 for (int j = 0; j < counter; j++)
22 if (cofficients[j] == cofficientsNew2[i]){
23 exists = true;
24 break;
25 }
26
27 if (!exists)
28 enterCoefficient(cofficientsNew2[i]);
29 }
30 }
It’s important to notice that the outer FOR loop is the same as before, but the inner FOR loop has its own counter “j” which iterates over the coefficients array. If a duplicate is found during the inner loop execution (if (coefficients[j] == coefficientsNew2[i])), the helper variable exists is set to true, and the inner loop is interrupted with break. A new element is inserted only if, after the inner loop ends, the variable exists remains false.
If we also don’t call the enterCoefficient method, then the constructor becomes even more complex because we would have to manually handle both inserting into the array and incrementing the counter:
1 FinancialCoefficients3(double[] cofficientsNew, int counterNew,
2 double[] cofficientsNew2, int counterNew2){
3 cofficients = new double[cofficientsNew.length + cofficientsNew2.length];
4
5 for (int i = 0; i < couterNew; i++){
6 boolean exists = false;
7
8 for (int j = 0; j < counter; j++)
9 if (cofficients[j] == cofficientsNew[i]){
10 exists = true;
11 break;
12 }
13
14 if (!exists && counter < cofficients.length){
15 cofficients[counter] = cofficientsNew[i];
16 counter++;
17 }
18 }
19
20 for (int i = 0; i < counterNew2; i++){
21 boolean exists = false;
22
23 for (int j = 0; j < counter; j++)
24 if (cofficients[j] == cofficientsNew2[i]){
25 exists = true;
26 break;
27 }
28
29 if (!exists && counter < cofficients.length){
30 cofficients[counter] = cofficientsNew2[i];
31 counter++;
32 }
33 }
34 }
This example clearly shows that introducing helper methods and/or calling existing methods (to handle part of the logic) leads to code that is shorter, more readable, and easier to maintain.
Comparing two arrays for equality
This is a relatively simple algorithm that checks whether two arrays are equal or not.
What does that mean exactly? In general, two arrays are equal if they have the same length and the same values in the same positions. If an element counter is used for the arrays, you should compare only the actually inserted elements, i.e., from index 0 to counter - 1, instead of going from 0 to length - 1. Additional rules can be added (e.g., order doesn’t matter, only values must be the same), but that won’t be covered here.
Example 9
Let’s say we have the following two arrays:
1 {1, 2, 3, 4}
2 {9, 5, 6}
They are clearly not equal since they’re not the same length and don’t have the same values. The following two arrays are also not equal because their lengths differ, even though the values 1, 2, 3, and 4 appear in both:
1 {1, 2, 3, 4}
2 {1, 2, 3, 4, 0}
Finally, the next two arrays are equal because they have the same length and the same values at the same positions:
1 {10, 19, 7, 9}
2 {10, 19, 7, 9}
Example 10
Take a look at the class FinancialCoefficients3 from the previous examples.
If we needed to add a method to compare an input array of coefficients to the class’s attribute coefficients (to check whether they are equal), that method could look like this:
1 boolean equalCoefficients(double[] coefficientsNew){
2 if (coefficientsNew == null || coefficientsNew.length != coefficients.length)
3 return false;
4
5 for (int i = 0; i < counter; i++)
6 if (coefficients[i] != coefficientsNew[i])
7 return false;
8
9 return true;
10 }
The method equalCoefficients returns true if the arrays coefficients and coefficientsNew are equal, and false otherwise. The first check is whether the input array is different from null (i.e., whether it’s initialized), and whether the two arrays have the same length. If either of those conditions is not met, the method immediately returns false and exits. This is checked early for efficiency, since there’s no point in comparing values if the arrays are not the same size — they are clearly different.
After that, a FOR loop with an inner if statement checks whether the values at the same positions match. As soon as a mismatch is found, the method returns false and exits.
It’s important to note that the loop goes from index 0 to counter - 1 because those are the actually inserted values (anything beyond that is uninitialized or considered “empty”). If a counter wasn’t used, all elements up to length - 1 would be compared, which might include empty or default values.
Finally, if no differences are found, the method returns true.
Most common errors
Some of the most common errors related to algorithms for adding values to an array that are not syntax errors, but affect the functioning of the program are:
- When copying an entire array, if only an assignment of the value of one variable representing an array to another variable is performed, a new array that is a copy of the existing one is not obtained, but rather two variables that point to the same array in memory:
1 MonthlyProfits(double[] monthlyProfits){
2 profits = monthlyProfits;
3 }
Instead, correctly:
1 MonthlyProfits(double[] monthlyProfits){
2 profits = new double[monthlyProfits.length];
3
4 for (int i = 0; i < monthlyProfits.length; i++)
5 profits[i] = monthlyProfits[i];
6 }
- When copying the entire array, if the array with the same name is re-declared (and initialized) as a local variable, the array (attribute) that was supposed to be initialized remains uninitialized (null), and therefore the copy is not made in it, but in the local variable:
1 double[] profits;
2
3 MonthlyProfits(double[] monthlyProfits){
4 // This is now a NEW LOCAL variable "profits"
5 // and not the attribute "profits" because it is re-declared
6 double[] profits = new double[monthlyProfits.length];
7
8 for (int i = 0; i < monthlyProfits.length; i++)
9 profits[i] = monthlyProfits[i];
10 }
Instead, correctly:
1 double[] profits;
2
3 MonthlyProfits(double[] monthlyProfits){
4 profits = new double[monthlyProfits.length];
5
6 for (int i = 0; i < monthlyProfits.length; i++)
7 profits[i] = monthlyProfits[i];
8 }
- When copying elements from one array into another existing array (which is not empty), re-initializing that second array (and/or setting the counter to zero) and thereby (mistakenly) deleting all its existing elements:
1 void enterGrades(int[] newGrades){
2 grades = new int[newGrades.length];
3 counter = 0;
4
5 for (int i = 0; i < newGrades.length; i++)
6 if (newGrades[i] >= 5 && newGrades[i] <= 10 && counter < grades.length) {
7 grades[counter] = newGrades[i];
8 counter++;
9 }
10 else System.out.println("ERROR");
11 }
Instead, correctly:
1 void enterGrades(int[] newGrades){
2 for (int i = 0; i < newGrades.length; i++)
3 if (newGrades[i] >= 5 && newGrades[i] <= 10 && counter < grades.length) {
4 grades[counter] = newGrades[i];
5 counter++;
6 }
7 else System.out.println("ERROR");
8 }
- When creating a new array by merging two existing arrays, forgetting that the new array should be initialized with a capacity equal to the sum of the capacities of the two arrays being merged (or larger than that sum). This will lead to an overflow of the new array’s capacity during merging, because not all elements will fit (Java will either throw an error, or the program itself will print “ERROR” through the insertion method if it checks whether there is room in the array):
1 FinancialCoefficients2(double[] coefficientsNew, int counterNew,
2 double[] coefficientsNew2, int counterNew2){
3 coefficients = new double[coefficientsNew.length];
4
5 for (int i = 0; i < counterNew; i++)
6 enterCoefficient(coefficientsNew[i]);
7
8 for (int i = 0; i < counterNew2; i++)
9 enterCoefficient(coefficientsNew2[i]);
10 }
Instead, correctly:
1 FinancialCoefficients2(double[] coefficientsNew, int counterNew,
2 double[] coefficientsNew2, int counterNew2){
3 coefficients = new double[coefficientsNew.length + coefficientsNew2.length];
4
5 for (int i = 0; i < counterNew; i++)
6 enterCoefficient(coefficientsNew[i]);
7
8 for (int i = 0; i < counterNew2; i++)
9 enterCoefficient(coefficientsNew2[i]);
10 }
- When creating a new array by merging two existing arrays, forgetting to copy only the elements that are actually entered (positions from 0 to counterNew - 1, and from 0 to counterNew2 - 1), which mistakenly results in copying all (positions from 0 to length - 1). This leads to copying all “free slots” from both arrays:
1 FinancialCoefficients2(double[] coefficientsNew, int counterNew,
2 double[] coefficientsNew2, int counterNew2){
3 coefficients = new double[coefficientsNew.length + coefficientsNew2.length];
4
5 for (int i = 0; i < coefficientsNew.length; i++)
6 enterCoefficient(coefficientsNew[i]);
7
8 for (int i = 0; i < coefficientsNew2.length; i++)
9 enterCoefficient(coefficientsNew2[i]);
10 }
Instead, correctly:
1 FinancialCoefficients2(double[] coefficientsNew, int counterNew,
2 double[] coefficientsNew2, int counterNew2){
3 coefficients = new double[coefficientsNew.length + coefficientsNew2.length];
4
5 for (int i = 0; i < counterNew; i++)
6 enterCoefficient(coefficientsNew[i]);
7
8 for (int i = 0; i < counterNew2; i++)
9 enterCoefficient(coefficientsNew2[i]);
10 }