Carlos Gordillo Carlos Gordillo - 5 months ago 14
Java Question

ArrayList error involving out of bounds exception

The rest of the code:

int j, k, l, tempA = 0, tempB = 0;
for (j = 0; j < 52; j++) {
// create temporary variables
for (k = 0; k < 13; k++) {
for (l = 0; l < 4; l++) {
tempA = rndm.get(k);
tempB = suit.get(l);
}
}
// increment # and convert into string
buttonNumber = buttonNumber+1;
buttonName = Integer.toString(buttonNumber);
// assign new button to the array
cardButton[j] = new JButton(buttonName);
// assign button image icon
cardButton[j].setIcon(cardImage[tempA][tempB]);
// assign value to the check variable
check[j] = Integer.toString(tempA+1);
// make button invisible for now
cardButton[j].setVisible(false);
// add the button to the board
board.add(cardButton[j]);
}


This is the error:

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 4, Size: 4


And in java code:

private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}


Ive seen multiple posts with this same error but it always comes up with the same answer: "you have not yet added values to the arraylist and as such trying to retreieve a value from position x wont work because there is no value there". But my problem is that i've set the values within the array beforehand, and im still getting the error.

Where I assign the arraylist:

ArrayList<Integer> rndm = new ArrayList<>();
ArrayList<Integer> suit = new ArrayList<>();
// set list size
for (int i = 0; i < 13; i++) {
rndm.add(i);
}
// set second list size
for (int i = 0; i < 4; i++) {
suit.add(i);
}


And where I use the .get function (which gives me the error):

for (j = 0, k = 0, l = 0; j < 52 || k < 13 || l < 4; j++, k++, l++) {
// create temporary variables
tempA = rndm.get(k);
tempB = suit.get(l);


the rest of the code is missing but that isn't where im getting the error from, just the two last lines up there ^

Answer

I believe your for-loop condition is incorrect. j < 52 || k < 13 || l < 4 will return true until j >= 52. Looking at your code, this throws an out of bounds error because k and l will also increase to 52. If I were you, I'd place them in separate conditions.

It appears (according to your comment) that you want to iterate over a 2D array. In that case, I'd use 2 for-loops:

for (k = 0; k < 13; k++) {
    for (l = 0; l < 4; l++) {
        tempA = rndm.get(k);
        tempB = suit.get(l);
        cardButton[k * 4 + l].setIcon(cardImage[tempA][tempB]);
        check[k * 4 + l] = Integer.toString(tempA+1);
    }
}

Note that we're replacing your j variable with some math instead. Every time you go through your l loop, k is incremented by one. Thus, we can tell what card we're on by multiplying k by 4, since l goes through 4 times. If we add l, we can get the current card that you're looking at. This code should work right out of the box.