Referential versus structural equality

This came up in class the other day.

Expressions involving the comparison operator (==) and two object references return true if the operands point to the same object. If you want to make a more meaningful comparison you have to override the equals method that all objects inherit from java.lang.Object.

See the Java code below to see how to override the equals method.

ref

public class EqualityDemo {

    public static void main(String[] args) {
        Student s = new Student("Fred", 123);
        Student t = s;
        Student u = new Student("Fred", 123);
        System.out.println(s==t);
        System.out.println(s==u);
        System.out.println(s.equals(u));
    }
}

class Student {

    String name;
    int id;

    public Student(String name, int id) {
        this.name = name;
        this.id = id;
    }   

    @Override
    public boolean equals(Object object) {
        Student student = (Student)object;
        return this.id == student.id && this.name.equalsIgnoreCase(student.name);
    }
}
Output:
true
false
true

Passing code as a parameter: An example of Java 8’s lambda expressions

In languages like Python and Javascript, functions are “first class objects”. This means that they can be assigned to variables and passed as parameters. In Java, if you want this functionality, you have to use an anonymous class or a lambda expression. Below are examples of the old-fashioned anonymous class technique, the new Lambda expression technique and, for comparison, the same code in Python and Javascript. EDIT: I’ve now also included Kotlin, a new language I’m quite interested in that compiles to Java bytecode and runs on the JVM.

Note the in the Lambda expression example there is no body provided for the execute() method. The fact that the Executable interface has a single method, and that the code passed in is interpreted as an Executable object, is sufficient for the compiler to know that the code passed in should be run when the execute() method is invoked.

Java

package lambdaexample;

public class Main {

    public static void main(String[] args) {
        doAnonymousClassExample();
        doLambdaExample();
    }

    // This method not required by Lambda example
    static void doAnonymousClassExample() {
        CodeRunner c = new CodeRunner();
        c.run(new Executable() {
            public void execute() {
                System.out.println("The code is running.");
            }
        });
    }

    // This method not required by anonymous class example
    static void doLambdaExample() {
        CodeRunner runner = new CodeRunner();
        runner.run(() -> System.out.println("The code is running."));
    }
}

interface Executable {
    void execute();
}

class CodeRunner {
    void run(Executable code) {
        System.out.println("About to run the code...");
        code.execute();
    }
}

Javascript

var foo = function() {
  console.log("The code is running.");
}

function codeExecuter(code) {
  console.log("About to run code...");
  code();
}

codeExecuter(foo);

Python

def codeexecuter(code):
    print("About to run code...")
    code()

foo = lambda : print("The code is running.")
codeexecuter(foo)

Kotlin

fun main (args: Array) {
    val foo: () -> Unit = { println("The code is running...") }
    codeExecuter(foo)
}

fun codeExecuter(code: () -> Unit) {
    println("About to run code...")
    code.invoke()
}

Java Multithreading Example

This is not on the IB Computer Science syllabus, but it’s useful for IAs and Grade 10 projects. One of the key reasons you might decide to run some code in its own thread is so that your GUI can remain responsive to user-generated events like button clicks. Imagine you have a sudoku game that displays a timer. You would need to run the timer in its own thread so that the game remained responsive to the user entering answers in the sudoku grid.

public class MultiThreadingExample {

    public static void main(String[] args) {
        /* Create five new tasks and set them running in their
         * own threads.
         */
        for (int i = 0; i < 5; i++) {
            /* Notice that because we don't re-use the task 
             * or thread objects, there is no need to assign
             * them to variables. This code is equivalent to
             *
             * Task task = new Task();
             * Thread thread = new Thread(task);
             * thread.start()
             */
            (new Thread(new Task())).start();
        }
    }
}

class Task implements Runnable {
     
    private static int nextId;
    private int id;
    
    public Task() {
        init();
    }
    
    private synchronized void init() {
        /* The synchronized keyword ensures that any thread
         * that runs this method runs the whole method before
         * yielding to another thread. This is necessary here
         * to prevent two threads from executing id = nextId
         * consecutively (in which case they will both get the
         * same id).
         */
        id = nextId;
        nextId = nextId + 1;        
    }
    
    public void run() {
        /* Each thread just counts up to 10 and prints out its
         * id and the number it has reached.
         */
        for(int i = 0; i < 10; i++) {
            System.out.println(id + ": " + i);
        }
    }
}

Confusion with lists in the IB Computer Science syllabus

There are three key mentions of the word list in the IB syllabus and they are all HL only:

  • Linked lists in Topic 5
  • ADT list in Option D
  • ArrayList and LinkedList in Option D

Topic 5 Linked Lists

This reference is all about how linked list objects work with references to the next node. You need to be able draw or construct simple code to show the changes that the list undergoes with insertion or deletion of a node. You should also certainly know the basic algorithm for traversing the list, e.g searching for an item within it.

Types of lists are singly-linked, doubly-linked, circular, etc, and a key point is that they only support serial access and, unlike arrays, don’t support direct access.

ADT list in Option D (D4.7)

ADT stands for Abstract Data Type. The “abstract” is there because we are not worrying at all about implementation, just what operations a list might support. What the IB wants you to understand here is that we can still talk about adding, removing, getting the next value, etc, without specifying exactly how the data is stored. In the past there have been questions that invent a list, along with the operations it supports, there and then on the question paper, and students are expected to construct code using the list.

You can look at abstract lists in Java using the two links below. You are certainly not expected to know the details of these classes/interfaces, you just need the general concepts mentioned above.

java.util.AbstractList
java.util.List

ArrayList and LinkedList (D4.11)

The syllabus says you should have a “broad understanding of the operation of these lists and their interface (methods)”. Oddly you are not expected to know the implementation, but it seems to me a key fact that the underlying data structure in an ArrayList is an array, and the underlying data structure in a LinkedList is, well, a linked list. This has great implications for the decision as to which to select. Anyway, have a brief look at the Javadoc pages linked above, and also looked at the new slide put into the Option D presentation showing techniques for iteration through each of these list types.