Relevant Reading Material

Arrays

Arrays in java provide mechanism to store a fixed size collection of values. The syntax of arrays in Java can be a little confusing.

Array Type

To define a variable that has an array type we need to use [] and the type of the element(s) to be stored in the array.

 Integer[] grades;  // an array that stores Integer objects
 String[] names; // an array that stores String objects

Array initialization

We can initialize an array in place

Integer[] grades = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

Or we allocate the space needed and then using the index operator to set each location in the array

Integer[] grades = new Integer[10]; // observer the use of `new` here even though there is no class

grades[0] = 0; // index starts at 0 not 1
grades[1] = 1;
grades[2] = 2;
grades[3] = 3;
grades[4] = 4;
grades[5] = 5;
grades[6] = 6;
grades[7] = 7;
grades[8] = 8;
grades[9] = 9;

Array access

Using the index operator.

What happens when we index something out of bounds?

Array length

Array objects provide methods and fields to their clients. length is the field that stores the max capacity of the array

 Integer[] grades = new Integer[10];
 System.out.println("Array size is: " + grades.length); // prints 10 even though there are no elements

 System.out.println(grades[0]); // What is the value at index 0?

Looping over arrays

The typical way to iterate over the array? for loop!

Integer[] grades = new Integer[10]; // observer the use of `new` here even though there is no class

grades[0] = 0; // index starts at 0 not 1
grades[1] = 10;
grades[2] = 20;
grades[3] = 30;
grades[4] = 40;
grades[5] = 50;
grades[6] = 60;
grades[7] = 70;
grades[8] = 80;
grades[9] = 90;

for(int i = 0; i < grades.length; i++){
    System.out.println("At index: " + i + " value is: " + grades[i]);
}

If you are not interested on the index or you are not performing computation that jumps around based on the index, there is a better (preferred) way to do this

for (Integer element : grades) {
    System.out.println("value is: " + element);
}

We can turn any for into a while loop

int i = 0;

while (i < grades.length) {
   System.out.println("At index: " + i + " value is: " + grades[i]);
   i++;  // equivalent to `i = i + 1;`
}

Looping, not just for arrays

Consider the following List ADT

public interface List<X> {

    public static <Y> List<Y> CreateEmpty(){
        // ...
    }

    public X getFirst();

    public Boolean isEmpty();

    public List<X> getRest();

    public List<X> add(X element);

}

We could loop over the list using a while loop

List<Integer> grades = List.CreateEmpty().add(10).add(20).add(30).add(40);

while(!grades.isEmpty()) {
    System.out.println("Element = " + grades.getFirst());
    grades = grades.getRest();
}

// lets do it in a for as well

for(; !grades.isEmpty();) {
    System.out.println("Element = " + grades.getFirst());
    grades = grades.getRest();
}

Multidimensional arrays

We can have a matrix (2-dimensional) arrays.

 Integer[][] matrix = new Integer[5][10]; // 5 arrays, each array with 10 elements

or even more dimensions

 Integer[][][] t = new Integer[5][10][3];  // can you draw the structure?

The main method in Java

So there is a special static method called main that Java uses as the entry point to your code.

class Main {

    public static void main(String[] args) {
        // start executing my program here!
    }
}

The argument to main is an array of String s that will hold the text passed to the JVM as extra arguments. We will talk more about this later in the semester.

Java Primitive Types

Up to this point we were using reference types in our Java programs. There are also primitive types as well. These is a second category of types and values that the Java language lets us use.

  • int, double, float, byte, short, long - deal with numbers at different precision and range

  • boolean - primitive type for true and false

  • char - primitive type for a unicode character

The primitives have a corresponding reference type with the same name, but the first name is Capital! Java 8, can automatically take in an int and turn it into an Integer, this is called boxing. Similarly Java can take a reference type and turn it into a primitive, i.e., Integer to int, this is called unboxing. These two operations boxing and unboxing are collectively called autoboxing.

Generics only work for reference types. Also, sometimes, autoboxing might lead to ambiguous method calls when a class has a method with the same name and return type one version of the method uses a primitive type as an argument and the other a reference type.

  public interface Adder{

      void add(int x);

      void add(Integer x);
  }

As a rule of thumb you should use primitive types for data that you would like to capture to which you do not want to add behaviour/operations (methods). Typically you would like to "wrap" your primitive data with a reference type that captures the information in your problem domain.

class Person {
    private Name name;
    private Age age;

    // methods elided
}

class Age {
    private int age;
    // methods elided
}

Lists with mutation

Lets try and implement this List interface

public interface List<X> {

  public static <Y> List<Y> CreateEmpty() {
      // FIXME : needs an implementation
  }

  void prepend(X element);

  void append(X element);

  Integer size();

  Boolean isEmpty();

  X getElement(Integer index);

}

Lets implement void remove(X element) as well.

Invariants

Can we keep track of the number of elements rather than counting them every time we are called?

We can keep a counter field that we update accordingly when we add (prepend or append) and remove.

Class Invariant is a boolean expression that captures what should always hold true about the state of this class' objects before the call to a public method and immediately after the return of a public method. The time spend executing the body of the method (including calling helper methods) we can temporarily break this invariant.

Another way to think of the invariant is a boolean expression that we logically-and with the public methods' pre and post conditions.