Numbers add

Premature expansion

public void add(int a) {
  numbers[size] = a;
  size++;
  if (numbers.length == size){
    int[] newArr = new int[size*2];
    for (int i = 0; i< size; i++){
      newArr[i] = numbers[i];
    }
    numbers = newArr;
  }
}

This works but consider what happens if you make a new Numbers with capacity one million and then add exactly one million numbers to it: after the last add, it expands numbers to an array that can hold two million numbers, half of which you never use.

Premature expansion, 2

public void add(int n) {
  if (size == numbers.length - 1) {
    int[] tmpNumbers = new int[size * 2];
    for (int i=0;i<numbers.length;i++) {
      tmpNumbers[i] = numbers[i];
    }
    numbers = tmpNumbers;
  }
  numbers[size] = n;
  size++;
}

Similar to the last one. Works but consider again what happens if you make a new Numbers with capacity one million and then add exactly one million numbers to it.

Duplicated code

public void add(int num) {
  if (size >= numbers.length) {
    int[] temp = new int[size * 2];
    for (int i = 0; i < numbers.length; i++) {
      temp[i] = numbers[i];
    }
    temp[size] = num;
    numbers = temp;
    size++;
  } else {
    numbers[size] = num;
    size++;
  }
}

Sightly de-duplicated code

public void add(int num) {
  if (size >= numbers.length) {
    int[] temp = new int[size * 2];
    for (int i = 0; i < numbers.length; i++) {
      temp[i] = numbers[i];
    }
    temp[size] = num;
    numbers = temp;
  } else {
    numbers[size] = num;
  }
  size++;
}

Emphasize duplication

public void add(int num) {
  if (size >= numbers.length) {
    int[] temp = new int[size * 2];
    for (int i = 0; i < numbers.length; i++) {
      temp[i] = numbers[i];
    }
    numbers = temp;
    numbers[size] = num;
  } else {
    numbers[size] = num;
  }
  size++;
}

Fully de-duplicated

public void add(int num) {
  if (size == numbers.length) {
    int[] temp = new int[size * 2];
    for (int i = 0; i < numbers.length; i++) {
      temp[i] = numbers[i];
    }
    numbers = temp;
  }
  numbers[size] = num;
  size++;
}

Flipping the arrays

public void add(int num) {
  if (size == numbers.length) {
    int[] old = numbers;
    numbers = new int[size * 2];
    for (int i = 0; i < old.length; i++) {
      numbers[i] = old[i];
    }
  }
  numbers[size] = num;
  size++;
}

Matter of taste but this version maybe shows more clearly that you’re copying from the old to the new array.

Using ++ as an expression

public void add(int num) {
  if (size == numbers.length) {
    int[] old = numbers;
    numbers = new int[size * 2];
    for (int i = 0; i < numbers.length; i++) {
      numbers[i] = old[i];
    }
  }
  numbers[size++] = num;
}

Not in the AP curriculum, but the ++ and -- operators can be used in expressions. They produce the value of the variable before the operator is applied and then change the variable.

Using a helper method

public void add(int num) {
  if (size == numbers.length) {
    numbers = expand(numbers);
  }
  numbers[size++] = num;
}

If we had that method, add would be really clear and simple. So let's write it:

private int[] expand(int[] ns) {
  int bigger = new int[ns.length * 2];
  for (int i = 0; i < ns.length; i++) {
    bigger[i] = ns[i];
  }
  return bigger;
}

Using a library method

// import java.util.Arrays at the top of the file

public void add(int num) {
  if (size == numbers.length) {
    numbers = Arrays.copyOf(numbers, size * 2);
  }
  numbers[size++] = num;
}

Again, beyond the AP curriculum but Java provides lots of useful methods like copyOf and part of becoming a good Java programmer is knowing about them or at least to look for them.