4

I am trying to write a method that determines the maximum value of an array list using tournament style comparisons. However, I guess I don't understand something about while loops because I cannot get the desired output and instead get an IndexOutOfBoundsException.

Here's my code:

import java.util.*;
public class TournamentMax {

public static <T extends Comparable<? super T>> ArrayList<T> tournament(ArrayList<T> tournamentArrayList) {
    ArrayList<T> winners = new ArrayList<T>();
    int n = tournamentArrayList.size();
    int upper;

    if (n % 2 != 0 ){ // if size is odd
        winners.add(tournamentArrayList.get(n));
        upper = n - 2;
    }

    else{  // if size is even
        upper = n - 1;
    }

    for (int index = 0; index < upper; index+=2){


        T winner = max(tournamentArrayList.get(index), tournamentArrayList.get(index + 1));
         System.out.println("Comparison between: " + tournamentArrayList.get(index) + " and " + tournamentArrayList.get(index + 1) );
         System.out.println("Winner was: " + winner);
        winners.add(winner);
    }

    return winners;     
}

public static <T extends Comparable<? super T>> T max (T obj1, T obj2){
    if (obj1.compareTo(obj2) > 0){
    return obj1;    
    }
    else return obj2;
}

public static <T extends Comparable<? super T>> ArrayList<T> maximum(ArrayList<T> tournamentArrayList){
    ArrayList<T> maximum = new ArrayList<T>();
    for (int i = 0; i < tournamentArrayList.size(); i++){
        maximum.add(tournamentArrayList.get(i));
    }
    while (maximum.size() > 1){
    System.out.println("maximum before tournament" + maximum);
    maximum = tournament(maximum);
    System.out.println("maximum after tournament and the one returned" + maximum);
    }   
    return maximum;


}

}

I know the problem is somewhere in this part:

while (maximum.size() > 1){
    System.out.println("maximum before tournament" + maximum);
    maximum = tournament(maximum);
    System.out.println("maximum after tournament and the one returned" + maximum);

In my head I'm trying to make the ArrayList be continually passed back to the tournament method until the ArrayList contains only one item, which should be the maximum. What confuses me even more is that the loop executes the first time and then the exception is thrown. I'm guessing I'm not using recursion correctly or something but if someone could point me in the right direction it would be much appreciated!

I'm using this as a test client:

public static void main(String... args) {
ArrayList<Integer> test = new ArrayList<Integer>();
test.add(12);
test.add(10);
test.add(65);
test.add(4);
test.add(78);
test.add(89);
test.add(99);
test.add(96);
test.add(24);
test.add(22);
ArrayList<Integer> testWinners = tournament(test);
System.out.println(testWinners);
ArrayList<Integer> testMaximum = maximum(test); 
System.out.println(testMaximum);


}
Stavrosnco
  • 77
  • 6
  • TL DR with this code heavy example; just go straight to Sbodd's answer and see the explanation of "Since list indexes start at 0, the last element in a list is at index size() - 1." – HRVHackers Apr 23 '16 at 04:52

1 Answers1

4

The following two lines will always throw an IndexOutOfBoundsException - which happens whenever your array size is odd:

int n = tournamentArrayList.size();
//...
winners.add(tournamentArrayList.get(n));

Since list indexes start at 0, the last element in a list is at index size() - 1.

Sbodd
  • 11,279
  • 6
  • 41
  • 42