gt: 		if (next == null) {
context: package cofh.lib.util;
  
  import com.google.common.base.Objects;
  import com.google.common.primitives.Ints;
  
  import java.util.AbstractCollection;
  import java.util.Collection;
  import java.util.ConcurrentModificationException;
  import java.util.Iterator;
  import java.util.ListIterator;
  import java.util.NoSuchElementException;
  
  @SuppressWarnings("unchecked")
  public class LinkedHashList<E extends Object> extends AbstractCollection<E> implements Cloneable {
  	// TODO: implements List<E>, java.io.Serializable
  
  	protected static final class Entry {
  
  		protected Entry next;
  		protected Entry prev;
  		protected final Object key;
  		protected final int hash;
  		protected Entry nextInBucket;
  
  		protected Entry(Object key, int keyHash) {
  
  			this.key = key;
  			this.hash = keyHash;
  		}
  	}
  
  	protected static int roundUpToPowerOf2(int number) {
  
  		return number >= Ints.MAX_POWER_OF_TWO
  				? Ints.MAX_POWER_OF_TWO
  						: (number > 2) ? Integer.highestOneBit((number - 1) << 1) : 2;
  	}
  
  	protected transient Entry head;
  	protected transient Entry tail;
  	protected transient int size;
  	protected transient int mask;
  	protected transient Entry[] hashTable;
  	protected transient int modCount;
  
  	public LinkedHashList() {
  
  		hashTable = new Entry[8];
  		mask = 7;
  	}
  
  	public LinkedHashList(int size) {
  
  		size = roundUpToPowerOf2(size);
  		hashTable = new Entry[size];
  		mask = size - 1;
  	}
  
  	public LinkedHashList(Collection<E> col) {
  
  		int size = roundUpToPowerOf2(col.size());
  		hashTable = new Entry[size];
  		mask = size - 1;
  		addAll(col);
  	}
  
  	protected int hash(Object n) {
  
  		int h = n == null ? 0 : n.hashCode();
  		h ^= (h >>> 20) ^ (h >>> 12);
  		return h ^ (h >>> 7) ^ (h >>> 4);
  	}
  
  	@Override
  	public int size() {
  
  		return size;
  	}
  
  	@Override
  	public boolean add(E e) {
  
  		return push(e);
  	}
  
  	public E get(int index) {
  
  		checkElementIndex(index);
  		return (E) index(index).key;
  	}
  
  	public boolean push(E obj) {
  
  		int hash = hash(obj);
  		if (seek(obj, hash) != null)
  			return false;
  
  		Entry e;
  		++modCount;
  		insert(e = new Entry(obj, hash));
  		rehashIfNecessary();
  		e.prev = tail;
  		e.next = null;
  		if (tail != null)
  			tail.next = e;
  		else
  			head = e;
  		tail = e;
  		return true;
  	}
  
  	public E pop() {
  
  		Entry e = tail;
  		if (e != null) {
  			++modCount;
  			delete(e);
  			tail = e.prev;
  			e.prev = null;
  			if (tail != null)
  				tail.next = null;
  			else
  				head = null;
  			return (E) e.key;
  		}
  		return null;
  	}
  
  	public E peek() {
  
  		return tail != null ? (E) tail.key : null;
  	}
  
  	public E poke() {
  
  		return head != null ? (E) head.key : null;
  	}
  
  	public boolean unshift(E obj) {
  
  		int hash = hash(obj);
  		if (seek(obj, hash) != null)
  			return false;
  
  		Entry e;
  		++modCount;
  		insert(e = new Entry(obj, hash));
  		rehashIfNecessary();
  		e.next = head;
  		e.prev = null;
  		if (head != null)
  			head.prev = e;
  		else
  			tail = e;
  		head = e;
  		return true;
  	}
  
  	public E shift() {
  
  		Entry e = head;
  		if (e != null) {
  			++modCount;
  			delete(e);
  			head = e.next;
  			e.next = null;
  			if (head != null)
  				head.prev = null;
  			else
  				tail = null;
  			return (E) e.key;
  		}
  		return null;
  	}
  
  	@Override
  	public boolean contains(Object obj) {
  
  		return seek(obj, hash(obj)) != null;
  	}
  
  	@Override
  	public boolean remove(Object obj) {
  
  		Entry e = seek(obj, hash(obj));
  		if (e == null)
  			return false;
  
  		unlink(e);
  		return true;
  	}
  
  	protected Entry index(int index) {
  
  		Entry x;
  		if (index < (size >> 1)) {
  			x = head;
  			for (int i = index; i --> 0; )
  				x = x.next;
  		} else {
  			x = tail;
  			for (int i = size - 1; i --> index; )
  				x = x.prev;
  		}
  		return x;
  	}
  
  	protected Entry seek(Object obj, int hash) {
  
  		for (Entry entry = hashTable[hash & mask];
  				entry != null;
  				entry = entry.nextInBucket)
  			if (hash == entry.hash && Objects.equal(obj, entry.key))
  				return entry;
  
  		return null;
  	}
  
  	protected void insert(Entry entry) {
  
  		int bucket = entry.hash & mask;
  		entry.nextInBucket = hashTable[bucket];
  		hashTable[bucket] = entry;
  		++size;
  	}
  
  	protected boolean linkBefore(E obj, Entry succ) {
  
  		int hash = hash(obj);
  		if (seek(obj, hash) != null)
  			return false;
  
  		final Entry pred = succ.prev;
  		final Entry newNode = new Entry(obj, hash);
  		modCount++;
  		insert(newNode);
  		rehashIfNecessary();
  		newNode.next = succ;
  		newNode.prev = pred;
  		succ.prev = newNode;
  		if (pred == null)
  			head = newNode;
  		else
  			pred.next = newNode;
  		return true;
  	}
  
  	protected void delete(Entry entry) {
  
  		l: synchronized (hashTable) {
  			int bucket = entry.hash & mask;
  			Entry prev = null, cur = hashTable[bucket];
  			if (cur == entry) {
  				hashTable[bucket] = cur.nextInBucket;
  				break l;
  			}
  			for (; true; cur = cur.nextInBucket) {
  				if (cur == entry) {
  					prev.nextInBucket = entry.nextInBucket;
  					break l;
  				}
  				prev = cur;
  			}
  		}
  		--size;
  	}
  
  	protected E unlink(Entry x) {
  
  		final E element = (E) x.key;
  		final Entry next = x.next;
  		final Entry prev = x.prev;
  
  		if (prev == null) {
  			head = next;
  		} else {
  			prev.next = next;
  			x.prev = null;
  		}
  
  