Sunday, February 15, 2015

The Ultimate Java 8 Linked List Reversal

Reversing a linked list...ah, the memories.  Losing that lucrative job offer because after 20 years someone thought I should have that on the tip of my tongue.  Whatever.

Well, indeed I can reverse a linked list, and it sucks.  In Java at least.

Here's what a Java 8 linked list reversal could look like:

class Node<T> {
    public Node<T> reverse () {return r(null);} 
    private Node<T> r(Node<T> reversed) {
        Node<T> rest = list;
        list = reversed;
        return rest == null ? this : rest.r(this);
    }
    T val;
    Node<T> list;
}

With the tail call optimization, that code takes O(1) space.

Since apparently no one wanted the tail call optimization, after adding an unhealthy dose of OOP, Java 8, Refactoring, and Patterns...what we have instead is:

public class Reverser<T> implements Iterable<T>{
    Node<T> n;
    Reverser(Node<T> n) {this.n = n;}
    @Override public Iterator<T> iterator() {return new RIterator<T>(this);}
    Node<T> setList(Node<T> reversed) {
        n.list = reversed;
        return n;
    }
    @SuppressWarnings("unchecked") public Node<T> reverse() {
        return (Node<T>) StreamSupport.stream(spliterator(), false)
            .reduce(null, (reversed, item) ->                                         (T)setList((Node<T>)reversed) );
    }

}

class RIterator<T> implements Iterator<T> {
    private Reverser<T> r;
    private Node<T> next;
    RIterator(Reverser<T> r) {
        this.r = r;
        next = r.n;
    }
    @Override public boolean hasNext() {return next != null;}
    @Override public  T next() {
        r.n = next;
        next = next.list;
        return null;
    }
}

I wish I was kidding.  And yes, the tests do pass.

Please no one else waste their time doing this.

Just write out the iterative algorithm in one method and forget about OOP.

Which I fear is pretty good advice in general.  Kingdom of the nouns indeed.

Next post...getting rid of those casts.

No comments:

Post a Comment