All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwt.emul.java.util.LinkedList Maven / Gradle / Ivy

There is a newer version: 2.10.0
Show newest version
/*
 * Copyright 2008 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package java.util;

import java.io.Serializable;

/**
 * Linked list implementation. [Sun
 * docs]
 * 
 * @param  element type.
 */
public class LinkedList extends AbstractSequentialList implements
    List, Queue, Serializable {
  /*
   * This implementation uses a doubly-linked circular list with a header node.
   * 
   * TODO(jat): add more efficient subList implementation.
   */

  /**
   * Implementation of ListIterator for linked lists.
   */
  private final class ListIteratorImpl implements ListIterator {

    /**
     * The index to the current position.
     */
    protected int currentIndex;

    /**
     * Current node, to be returned from next.
     */
    protected Node currentNode;

    /**
     * The last node returned from next/previous, or null if deleted or never
     * called.
     */
    protected Node lastNode = null;

    /**
     * @param index from the beginning of the list (0 = first node)
     * @param startNode the initial current node
     */
    public ListIteratorImpl(int index, Node startNode) {
      currentNode = startNode;
      currentIndex = index;
    }

    public void add(E o) {
      addBefore(o, currentNode);
      ++currentIndex;
      lastNode = null;
    }

    public boolean hasNext() {
      return currentNode != header;
    }

    public boolean hasPrevious() {
      return currentNode.prev != header;
    }

    public E next() {
      if (!hasNext()) {
        throw new NoSuchElementException();
      }
      lastNode = currentNode;
      currentNode = currentNode.next;
      ++currentIndex;
      return lastNode.value;
    }

    public int nextIndex() {
      return currentIndex;
    }

    public E previous() {
      if (!hasPrevious()) {
        throw new NoSuchElementException();
      }
      lastNode = currentNode = currentNode.prev;
      --currentIndex;
      return lastNode.value;
    }

    public int previousIndex() {
      return currentIndex - 1;
    }

    public void remove() {
      verifyCurrentElement();
      if (currentNode == lastNode) {
        // We just did a previous().
        currentNode = lastNode.next;
      } else {
        // We just did a next().
        --currentIndex;
      }
      lastNode.remove();
      lastNode = null;
      --size;
    }

    public void set(E o) {
      verifyCurrentElement();
      lastNode.value = o;
    }

    protected void verifyCurrentElement() {
      if (lastNode == null) {
        throw new IllegalStateException();
      }
    }
  }

  /**
   * Internal class representing a doubly-linked list node.
   * 
   * @param  element type
   */
  private static class Node {
    public Node next;
    public Node prev;
    public E value;

    public Node() {
      next = prev = this;
    }

    public Node(E value) {
      this.value = value;
    }

    /**
     * Construct a node containing a value and add it before the specified node.
     * 
     * @param value
     * @param nextNode
     */
    public Node(E value, Node nextNode) {
      this(value);
      this.next = nextNode;
      this.prev = nextNode.prev;
      nextNode.prev.next = this;
      nextNode.prev = this;
    }

    /**
     * Remove this node from any list it is in, leaving it with circular
     * references to itself.
     */
    public void remove() {
      this.next.prev = this.prev;
      this.prev.next = this.next;
      this.next = this.prev = this;
    }
  }

  /**
   * Ensures that RPC will consider type parameter E to be exposed. It will be
   * pruned by dead code elimination.
   */
  @SuppressWarnings("unused")
  private E exposeElement;

  /**
   * Header node - header.next is the first element of the list, and header.prev
   * is the last element of the list. If the list is empty, the header node will
   * point to itself.
   */
  private Node header;

  /**
   * Number of nodes currently present in the list.
   */
  private int size;

  public LinkedList() {
    clear();
  }

  public LinkedList(Collection c) {
    this();
    addAll(c);
  }

  @Override
  public boolean add(E o) {
    addLast(o);
    return true;
  }

  public void addFirst(E o) {
    new Node(o, header.next);
    ++size;
  }

  public void addLast(E o) {
    new Node(o, header);
    ++size;
  }

  @Override
  public void clear() {
    header = new Node();
    size = 0;
  }

  public E element() {
    return getFirst();
  }

  public E getFirst() {
    throwEmptyException();
    return header.next.value;
  }

  public E getLast() {
    throwEmptyException();
    return header.prev.value;
  }

  @Override
  public ListIterator listIterator(final int index) {
    if (index < 0 || index > size) {
      indexOutOfBounds(index, size);
    }

    Node node;
    // start from the nearest end of the list
    if (index >= size >> 1) {
      node = header;
      for (int i = size; i > index; --i) {
        node = node.prev;
      }
    } else {
      node = header.next;
      for (int i = 0; i < index; ++i) {
        node = node.next;
      }
    }

    return new ListIteratorImpl(index, node);
  }

  public boolean offer(E o) {
    return add(o);
  }

  public E peek() {
    if (size == 0) {
      return null;
    } else {
      return getFirst();
    }
  }

  public E poll() {
    if (size == 0) {
      return null;
    } else {
      return removeFirst();
    }
  }

  public E remove() {
    return removeFirst();
  }

  public E removeFirst() {
    throwEmptyException();
    --size;
    Node node = header.next;
    node.remove();
    return node.value;
  }

  public E removeLast() {
    throwEmptyException();
    --size;
    Node node = header.prev;
    node.remove();
    return node.value;
  }

  @Override
  public int size() {
    return size;
  }

  private void addBefore(E o, Node target) {
    new Node(o, target);
    ++size;
  }

  /**
   * Throw an exception if the list is empty.
   */
  private void throwEmptyException() {
    if (size == 0) {
      throw new NoSuchElementException();
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy