Generics in Logo

Starting with version 1.5, Java has added support for generics, also known as parameterized types.

As an example of a generic method, slicesIndex takes a list of any Comparable type and an element of that type and returns the index of the first occurrence of v in list, or -1 if not present. The Comparable interface ensures that we can compare values of this type with the compareTo method.

public class Generics {
    public static <T extends Comparable<T>> int slicesIndex(List<T> list, T v) {
        for (int i = 0; i < list.size(); i++) {
            if (v.compareTo(list.get(i)) == 0) {
                return i;
            }
        }
        return -1;
    }

    public static class List<T> {
        private Node<T> head;
        private Node<T> tail;

        private static class Node<T> {
            T val;
            Node<T> next;

            Node(T val) {
                this.val = val;
            }
        }

        public void push(T v) {
            if (tail == null) {
                head = new Node<>(v);
                tail = head;
            } else {
                tail.next = new Node<>(v);
                tail = tail.next;
            }
        }

        public List<T> allElements() {
            List<T> elements = new ArrayList<>();
            for (Node<T> e = head; e != null; e = e.next) {
                elements.add(e.val);
            }
            return elements;
        }
    }

    public static void main(String[] args) {
        List<String> s = Arrays.asList("foo", "bar", "zoo");

        System.out.println("index of zoo: " + slicesIndex(s, "zoo"));

        List<Integer> lst = new List<>();
        lst.push(10);
        lst.push(13);
        lst.push(23);
        System.out.println("list: " + lst.allElements());
    }
}

When invoking generic methods, we can often rely on type inference. Note that we don’t have to specify the type for T when calling slicesIndex - the compiler infers it automatically.

As an example of a generic type, List is a singly-linked list with values of any type.

We can define methods on generic types just like we do on regular types, but we have to keep the type parameters in place. The type is List<T>, not List.

allElements returns all the List elements as a Java List.

When running this program, you should see output similar to:

index of zoo: 2
list: [10, 13, 23]

This example demonstrates how generics in Java allow for type-safe collections and algorithms that can work with different types while still providing compile-time type checking.