Reputation: 392
I've been studying for my upcoming Java exam, and i'm having a hard time wrapping my head around 2D arrays. I have the basics down, such as creating and initializing a 2D array, but when it comes to inserting, deleting, or even sorting through one, I get pretty confused. My professor spent all of 10 minutes going over the basics but on our exam, we are expected to know how to create a 2D array of objects and manipulate the data by inserting, deleting, and sorting the objects in the array. He makes us hand-write all of our code on our exams, so no computers are allowed to assist in the process. I've spent hours pouring over examples both here and on other sites, but I still don't feel like I understand the material well enough to hand write all my code and get it right.
My confusion mostly stems from the nested for
loops usually used to move thru a 2D array. I can see how other people do it and copy that, but I still don't understand why the loops work as they do. I'm sure i'm in the minority here, but for whatever reason the logic behind it has me completely lost.
Take this(albeit poor) example i've been working on to help myself understand 2D arrays(as well as the rest of the exam material). Say you run a car dealership and you want to order cars to fill your stock. The program starts with a top abstract
class that describes the cars you are selling in general(in my case Audi). The dealership offers 4 models of Audi's, an A4
, A6
, A8
, and R8
. All these cars(classes) inherit methods from the super
, named Audi
. I then want to create a 2D array to store the cars in stock. This will be used in another class defined by me, including methods to search()
, delete()
, and sort()
. Let's call it AudiDealership
. The dealer can only hold 3 of each model, so the array would be something like Audi[4][3]
. The A4's would fill the first row, subscript 0
, A6 fills subscript 1
, ect. How would I set up the for
loops to insert/delete from the proper row? I obviously don't want an A4 inserted into a row that should hold an A6, and so on.
Again, I can stare at code all day and copy it, but I want to understand why/how the loops work as they do. I apologize if this topic seems trivial or has been beaten to death, but all the reading i've done before posting this has left me just as confused as before. Many of you on this site are fantastic teachers in your own right, so I thought someone may be able to explain this in a way that I can understand. My professor hasn't been any help in this regard, so i'm using external means to try and figure things out. I greatly appreciate any advice or explanation in advance :)
Upvotes: 3
Views: 6523
Reputation: 465
It helps to think of 2D arrays as arrays that hold other arrays. Such as Cars[0][5]
is accessing a car array at 0 and the actual car is found in position 5 of that array. Cars[1][5]
would access the second car array at position 1 and the car is found at 5 of the array that's in position 1. This code might help you understand it a bit more:
public class TwoDArray {
public static void main(String[] args)
{
Cars[][] cars; // declaring my 2D array.
cars = new Cars[4][]; // making the x axis 4 cars wide.
// now we will step along the x axis and create a Cars array in each slot.
for ( int a = 0; a < cars.length; a++) // cars.length = how wide.
{
cars[a] = new Cars[3]; // creating a new Cars[] in each slot of our 2D Car array @ position a.
//cars[a] = new 1D Cars array in slot a, length of 3.
}
// Note that we could have also created our array like this.
// Cars[][] cars = new Cars[4][3];
for ( int x = 0; x < cars.length; x++) //stepping along the x axis. cars.length = how wide.
{ //every time we step thru x we will execute this next loop.
for ( int y = 0; y < cars[x].length; y++) // stepping along the y axis. cars[x].length = how long.
{ // this loop will cycle through the y axis each time we increment x
cars[x][y] = new Cars( 2014, "someAudi", x + " " + y ); // creating a new car(s) @ x,y position.
}
}
// now to just print them.
for ( int x = 0; x < cars.length; x++) //stepping along the x axis again.
{
for ( int y = 0; y < cars[x].length; y++) // stepping along the y axis.
{
System.out.println(cars[x][y].getYear() +
" " + cars[x][y].getModel() +
" " + cars[x][y].getName() +
" " + cars[x][y].getManufacturer()); // the super method.
}
}
//INSERTION.
// To insert into your array, you simply need to provide the coordinates to insert the new Car(s) object.
// This next line will insert a new Car into the array at position 1 and the number 2 element of that array.
cars[1][2] = new Cars( 2014, "someAudi", "My Favorite Car!");
System.out.println(); // Just adding a space between outputs.
for ( Cars[] c: cars) //extracting each Cars array and name it c from the 2D Cars array named cars.
{ //basically stepping along the x axis and getting each array stored in x.
for ( Cars car: c) // Now we are stepping along the y axis.
{ // We are getting each individual Cars object and naming it car
// from each Cars[] named c from our first loop.
System.out.println(car.getYear() +
" " + car.getModel() +
" " + car.getName() +
" " + car.getManufacturer()); // the super method.
}
}
// NOTE* if you wish to insert a new element and do not have extra capacity then you will need to
// create a larger array @ cars[x]. cars[x] = new Cars[newSize];.
// DELETION.
// To delete an element you can just simply overwrite it.
// such as:
cars[1][1] = new Cars( 2014, "someAudi", "new Audi"); // Essentially we deleted and inserted a new object
// at position [1][1].
// If you just want to completely remove the element then you will need to update the size of the array.
// You can define a new array to hold the values of the old array minus the element that should be deleted.
Cars[] newArray = new Cars[cars[2].length - 1]; // We will use the array stored in cars[2] for this example.
// we set the length to one less to completely get rid of the
// old element.
int deleteThisPosition = 1; // We will use this variable to store the position that will be deleted from
// the array stored in cars[2].
int newArrayPosition = 0; // We will use this to increment our position in the new array along with `a`
// in the next for loop.
for ( int a = 0; a < cars[2].length; a++)
{
if ( a == deleteThisPosition) // if it reaches this position we will advance `a` and exclude it from
a++; // our new array.
newArray[newArrayPosition] = cars[2][a]; // we will store the value @ position `a` from the array in cars[2]
// into our newArray @ position `newArrayPosition`.
newArrayPosition++; // incrementing our variable to stay parallel with the array in cars[2].
}
//Now we can just assign the newArray to cars[2]. You will notice that Car `2 1` is no longer present.
cars[2] = newArray;
System.out.println(); // Just adding a space between outputs.
for ( Cars[] c: cars)
{
for ( Cars car: c)
{
System.out.println(car.getYear() +
" " + car.getModel() +
" " + car.getName() +
" " + car.getManufacturer()); // the super method.
}
}
}
}
Here are the other classes from your example.
Audi class:
public abstract class Audi {
public String getManufacturer() { return "Audi"; } // method from this super class.
}
Cars class:
public class Cars extends Audi{ //extending Audi.
private String model;
private String name;
private int year;
Cars(int year, String model, String name)
{
this.year = year;
this.model = model;
this.name = name;
}
public String getName() { return name; }
public String getModel() { return model; }
public int getYear() { return year; }
}
If you run the code you will notice the pattern in the names of the cars.
Output:
Notice the pattern in each car's name, the unique column. It corresponds to how we stepped through our loops. We started with x and for each x we looped through y. x + " " + y
was how we named each car in the code above.
Upvotes: 2
Reputation: 264
Let me give you an example:
StringBuilder output = new StringBuilder();
for (int i = 0; i < table.length; i++) {
for (int j = 0; j < table[i].length; j++) {
output.append(table[i][j]);
}
output.append("\n");
}
This would be the code to loop through a 2 dimensional array.
The code goes directly into the first row. This is the i-value. As you want to loop through every column of the row, you need to know the length of the row to loop through it.
So you start in the first row, and go right to the end which is table[i].length. In the first row the first length would be table[0].length. And this length is 3 as you have 3 columns in each row.
As we're now done with looping through the first row, we get to second row. By going into the second row i increases by one. So our pointer shows now in row 2 (The i in table[i].length is now 1 because it always starts at 0) and so on.
Our pointer goes through every row and thats just how it works. with every new row the pointer of i increases by 1 (that's the i++ in the for loop).
With every new column in one row the j increases and the i stays the same. The i only changes when you're entering a new row. And the j changes by entering a new column.
Hope this helps ;)
EDIT.:
Another example :
if you would like to get the value of the 3rd column in the 4th row:
The value you want is inside here: table[3][2];
Remember arrays always start counting at 0. :)
Upvotes: 1
Reputation: 1663
Audi[4][3] cars = ... // your 2D array of all cars
As you correctly specified,
The A4's would fill the first row, subscript 0, A6 fills subscript 1, ect.
which translates to cars[0]
holds Audi[] with A4 instances
, cars[1]
holds Audi[] with A6 instances
etc.
OK, so
Audi[] A4s = cars[0];
Audi[] A6s = cars[1];
...
Then you could say that
Audi A4_1 = A4s[0];
Audi A4_2 = A4s[1];
Audi A4_3 = A4s[2];
...
And repeat it for each car you have. But this is a wrong approach. First we generalize access to each car.
If you want to traverse specific cars in each model array, you need to have a for-loop with index called, say, specificCarIndex
. Loop to traverse an array of A4s
will be simple:
for (int specificCarIndex = 0; specificCarIndex < 3; specificCarIndex++) {
// Here A4s[specificCarIndex] contains an object of concrete Audi car of model A4
}
To traverse array of another model (like A6) you do the same, replacing A4s
with A6s
and so on.
Now we need to generalize everything.
for (int carModelIndex = 0; carModelIndex < 4; carModelIndex++) {
// Here cars[carModelIndex] holds an array of specific Audi model as you mentioned before
}
cars[carModelIndex]
essentially is Audi[] A4s
if carModelIndex == 0
, then Audi[] A6s
if carModelIndex == 1
and so on.
Now that we know how to access array of each Audi model, and we know how to access individual cars in each model array, we combine the two:
for (int carModelIndex = 0; carModelIndex < 4; carModelIndex++) {
for (int specificCarIndex = 0; specificCarIndex < 3; specificCarIndex++) {
// Here cars[carModelIndex][specificCarIndex] holds an object of type Audi which refers to a specific car
// If double index seems difficult, consider this:
// Audi[] audis = cars[carModelIndex] (array like A4s, A6s...)
// Audi audi = audis[specificCarIndex] (specific car)
// Just as in the examples before for-loops.
}
}
Upvotes: 1