package com.johnChnia.coding2017.basic;
import java.util.Arrays;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* Created by john on 2017/3/8.
*
* @// TODO: 学会多线程后,实现Iterator 的 remove 方法
*/
public class ArrayList<E> implements List<E> {
private Object[] elementData;
private int size = 0;
private static final int DEFAULTCAPACITY = 10;
/**
* Constructs an list with the default capacity.
*/
public ArrayList() {
elementData = new Object[DEFAULTCAPACITY];
}
/**
* Constructs an list with the specified initial capacity.
*
* @param initialCapacity capacity of arrayList.
* @throws IllegalArgumentException if the specified initial capacity
* is negative or zero
*/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
elementData = new Object[initialCapacity];
} else {
throw new IllegalArgumentException("Illegal Capacity: " +
initialCapacity);
}
}
/**
* Returns the element at the specified position in this list.
*
* @param index index of the element to return
* @return the element at the specified position in this list
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E get(int index) {
rangeCheck(index);
return (E) elementData[index];
}
/**
* Appends the specified element to the end of this list.
*
* @param element element to be appended to this list
*/
public void add(E element) {
ensureCapacityInternal(size + 1);
elementData[size++] = element;
}
/**
* Inserts the specified element at the specified position in this
* list. Shifts the element currently at that position (if any) and
* any subsequent elements to the right (adds one to their indices).
*
* @param element element to be inserted
* @param index index at which the specified element is to be inserted
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public void add(int index, E element) {
rangeCheck(index);
ensureCapacityInternal(size + 1);
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
/**
* Removes the element at the specified position in this list.
* Shifts any subsequent elements to the left (subtracts one from their
* indices).
*
* @param index the index of the element to be removed
* @return the element that was removed from the list
* @throws IndexOutOfBoundsException {@inheritDoc} index out of B
*/
public E remove(int index) {
rangeCheck(index);
Object oldValue = elementData[index];
int numMoved = size() - index - 1;
if (numMoved > 0) {
System.arraycopy(elementData, index + 1, elementData, index,
numMoved);
}
elementData[--size] = null; // let jc to clear
return (E) oldValue;
}
/**
* Returns the index of the first occurrence of the specified element
* in this list, or -1 if this list does not contain the element.
* More formally, returns the lowest index <tt>i</tt> such that
* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>,
* or -1 if there is no such index.
*/
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i] == null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
/**
* Returns <tt>true</tt> if this list contains no elements.
*
* @return <tt>true</tt> if this list contains no elements
*/
public boolean empty() {
return size == 0;
}
/**
* Returns the number of elements in this list.
*
* @return the number of elements in this list
*/
public int size() {
return size;
}
@Override
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
int cursor = 0;
@Override
public boolean hasNext() {
return cursor != size;
}
@Override
public E next() {
int i = cursor;
if (i >= size) {
throw new NoSuchElementException();
}
Object[] elementData = ArrayList.this.elementData;
cursor = i + 1;
return (E) elementData[i];
}
}
/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the double length of list.
*/
private void grow() {
elementData = Arrays.copyOf(elementData,
2 * elementData.length);
}
public boolean contains(Object o) {
Itr itr = new Itr();
if (o == null) {
while (itr.hasNext()) {
if (itr.next() == null) {
return true;
}
}
} else {
while (itr.hasNext()) {
if (itr.next().equals(o)) {
return true;
}
}
}
return false;
}
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("[");
for (int index = 0; index < size(); index++) {
stringBuilder.append(elementData[index]);
stringBuilder.append(", ");
}
stringBuilder.append("]");
return stringBuilder.toString();
}
private void ensureCapacityInternal(int minCapacity) {
if (minCapacity - elementData.length > 0)
grow();
}
public Object[] toArray() {
return Arrays.copyOf(elementData, size());
}
/**
* Constructs an IndexOutOfBoundsException detail message.
* Of the many possible refactorings of the error handling code,
* this "outlining" performs best with both server and client VMs.
*/
private String outOfBoundsMsg(int index) {
return "Index: " + index + ", Size: " + elementData.length;
}
/**
* Checks if the given index is in range. If not, throws an appropriate
* runtime exception. This method does *not* check if the index is
* negative: It is always used immediately prior to an array access,
* which throws an ArrayIndexOutOfBoundsException if index is negative.
*/
private void rangeCheck(int index) {
if (index < 0 || index >= size()) {
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
}
}