Simple linked list class which uses a Comparator to sort the nodes.
// // Copyright (C) CSIRO Australia Telescope National Facility // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. //package atnf.atoms.mon.util; import java.util.Comparator; import java.util.Vector; /** * Simple linked list class which uses a Comparator to sort the nodes. Most * operations are completed in linear time in the worst case. * * @author David Brodrick */ public class SortedLinkedList { /** Trivial class for each list node. */ private class ListNode { /** The data stored at this node. */ Object data = null; /** Pointer to the next node. */ ListNode next = null; ListNode(Object o) { data = o; } ListNode(Object o, ListNode n) { data = o; next = n; } } /** Comparator to use. */ protected Comparator itsComparator = null; /** Head of the list. */ protected ListNode itsHead = null; /** Tail of the list. */ protected ListNode itsTail = null; /** Record the current number of nodes in the list. */ protected int itsSize = 0; /** * Constructor. * * @param c * The Comparator to use to compare elements. */ public SortedLinkedList(Comparator c) { itsComparator = c; } /** Add the Object to the set. */ public synchronized void add(Object o) { if (o == null) { return; } ListNode newnode = new ListNode(o); if (itsHead == null) { // The list was empty itsHead = itsTail = new ListNode(o); } else { // Check if it needs to go right at the head if (itsComparator.compare(o, itsHead.data) <= 0) { newnode.next = itsHead; itsHead = newnode; } // Check if it needs to go right at the tail else if (itsComparator.compare(o, itsTail.data) >= 0) { itsTail.next = newnode; itsTail = newnode; } else { // It needs to be inserted into the middle of the list ListNode next = itsHead.next; ListNode prev = itsHead; while (itsComparator.compare(o, next.data) > 0) { prev = next; next = next.next; } // Do the actual insertion prev.next = newnode; newnode.next = next; } } itsSize++; } /** Remove all instances of the object from the set. */ public synchronized void remove(Object o) { ListNode next = itsHead; ListNode prev = null; while (next != null) { if (next.data == o) { // Need to remove this node itsSize--; if (prev != null) { // It's not the head prev.next = next.next; } else { // It was the head itsHead = next.next; } // Check if it's the tail if (next == itsTail) { itsTail = prev; } } prev = next; next = next.next; } } /** Return a reference to the first node but do not remove it */ public synchronized Object first() { if (itsHead == null) { return null; } else { return itsHead.data; } } /** * Return all elements less than the argument and remove them from the list. */ public synchronized Vector headSet(Object o) { Vector<Object> res = new Vector<Object>(); // Keep adding the head until it no longer matches while (itsHead != null && itsComparator.compare(itsHead.data, o) < 0) { res.add(itsHead.data); itsSize--; if (itsHead == itsTail) { // the list has been emptied itsHead = itsTail = null; break; } itsHead = itsHead.next; } return res; } /** * Check if the list is empty. * * @return <code>True</code> if the list is empty. */ public synchronized boolean isEmpty() { if (itsHead == null) { return true; } assert itsSize > 0; return false; } /** Check if the object is already stored in the list. */ public synchronized boolean contains(Object o) { ListNode next = itsHead; while (next != null) { if (next.data == o) { return true; } next = next.next; } return false; } /** Get a string representation of the list. */ public synchronized String toString() { String res = "[ "; ListNode next = itsHead; while (next != null) { res = res + next.data.toString() + " "; next = next.next; } res = res + " ]"; return res; } /** Return the number of nodes currently in the list. */ public int size() { return itsSize; } }