数组与集合的转换
- 集合 --> 数组
Collection: T[] toArray(T[] arr); - 数组 --> 集合
static List asList(T… a) 视图方法
但是不能增加和删除元素
jdk5特性:
a.泛型
b.自动装箱和自动拆箱
c.静态导入
d.foreach
e.可变长参数
public static void main(String[] args) {
Integer[] arr = {1, 2, 3, 4, 5};
List<Integer> list = Arrays.asList(arr); // 视图方法
System.out.println(list);
添加元素:不可
list.add(6); // UnsupportedOperationException
删除元素:不可
list.remove(0); // UnsupportedOperationException
修改元素:可
list.set(0, 100);
System.out.println(list);
System.out.println(Arrays.toString(arr));
}
数据结构
- 数据结构是相互之间存在一种或多种特定关系的数据元素的集合。
- 公式:数据结构=数据+结构
- 数据:用类型表示结构:在任何问题中,数据元素都不是孤立存在的,它们之间都存在着某种关系,这种数据元素相互之间的关系称为结构。
- 元素之间,通常有以下四种基本结构:
a.集合:结构中的数据元素之间除了同属于一个集合的关系之外,别无其他关系。这里的集合和数学中集合的概念是一致的。
b.线性结构:结构中的数据元素之间存在一个对一个的关系。
c.树形结构图:结构中的数据元素之间存在一个对多个的关系。
d.网状结构:结构中的数据元素之间,存在多个对多个的关系。
逻辑结构&物理结构
- 前面分类中定义的关系,描述的是数据元素间的逻辑关系,因此又称为逻辑结构。
- 但是仅仅知道数据元素间的逻辑关系是不够的,因为我们得实现自己的数据结构。 因此,我们得关注数据结构在计算机底层是如何表示的?
- 数据结构在计算机中的表示,称为数据的物理结构,又称为存储结构或者映像。
结构的表示可分为两种:顺序存储结构 (顺序映像) 和 链式存储结构 (非顺序映像)。
- 顺序映像:借助元素在存储器中的相对位置来表示数据元素之间的逻辑关系。(数组)
- 非顺序映像:借助指示元素存储地址的”指针”,来表示数据元素的逻辑关系。(链表)
线性表:
- 顺序映像 (ArrayList)
- 非顺序映像 (LinkedList)
MyArrayList
为什么在迭代器遍历的时候,用集合的API删除倒数第二个元素不会报异常?
import com.cskaoyan.exception.ArrayListOverflowException;
import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class MyArrayList<E> implements MyList<E> {
private static final int DEFAULT_CAPACITY = 10;
private static final int MAX_CAPACITY = Integer.MAX_VALUE - 8;
// 属性
private Object[] elements;
private int size;
private int modCount;//集合结构被修改的次数
// 构造方法
public MyArrayList() {
elements = new Object[DEFAULT_CAPACITY];
}
public MyArrayList(int initialCapacity) {
// 及早失败原则
if (initialCapacity <= 0 || initialCapacity > MAX_CAPACITY) {
throw new IllegalArgumentException("initialCapacity=" + initialCapacity);
}
elements = new Object[initialCapacity];
}
/**
* 在线性表的末尾添加元素
*
* @param e 待添加的元素
* @return 如果添加成功返回true
*/
@Override
public boolean add(E e) {
add(size, e);
return true;
}
/**
* 在线性表中指定索引位置添加元素
*
* @param index 指定索引位置
* @param e 待添加的元素
*/
@Override
public void add(int index, E e) {
checkIndexForAdd(index);
// 判断是否需要扩容
if (size == elements.length) {
int minCapacity = size + 1;
// 计算新数组的大小
int newCapacity = calculateCapacity(minCapacity);
// 扩容
grow(newCapacity);
}
// 添加元素
for (int i = size; i > index; i--) {
elements[i] = elements[i - 1];
}
elements[index] = e;
size++;
modCount++;
}
private void grow(int newCapacity) {
Object[] newArr = new Object[newCapacity];
for (int i = 0; i < size; i++) {
newArr[i] = elements[i];
}
elements = newArr; //Caution!
}
private int calculateCapacity(int minCapacity) {
if (minCapacity > MAX_CAPACITY || minCapacity < 0) {
throw new ArrayListOverflowException();
}
// 一定能够容纳minCapacity个元素
int newCapacity = elements.length + (elements.length >> 1);
if (newCapacity > MAX_CAPACITY || newCapacity < 0) {
newCapacity = MAX_CAPACITY;
}
// 返回minCapacity和newCapacity的最大值
return minCapacity > newCapacity ? minCapacity : newCapacity;
}
private void checkIndexForAdd(int index) {
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException("index=" + index + ", size=" + size);
}
}
/**
* 清空所有元素
*/
@Override
public void clear() {
for (int i = 0; i < size; i++) {
elements[i] = null;
}
size = 0;
modCount++;
}
/**
* 判断线性表中是否有与指定对象o相等的元素
*
* @param o 指定对象
* @return 如果存在与o相等的元素返回true, 否则返回false.
*/
@Override
public boolean contains(Object o) {
return indexOf(o) != -1;
}
/**
* 获取指定索引位置的元素
*
* @param index 指定索引位置
* @return 该索引位置的元素
*/
@Override
@SuppressWarnings("unchecked")
public E get(int index) {
checkIndex(index);
return (E) elements[index];
}
private void checkIndex(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("index=" + index + ", size=" + size);
}
}
/**
* 获取线性表中第一个与指定对象o相等元素的索引
*
* @param o 指定对象
* @return 第一个与指定对象o相等元素的索引, 如果线性表中没有这样的元素返回-1
*/
@Override
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++) {
if (elements[i] == null) return i;
}
} else {
for (int i = 0; i < size; i++) {
if (o.equals(elements[i])) return i;
}
}
return -1;
}
/**
* 获取线性表中最后一个与指定对象o相等元素的索引
*
* @param o 指定对象
* @return 最后一个与指定对象o相等元素的索引, 如果线性表中没有这样的元素返回-1
*/
@Override
public int lastIndexOf(Object o) {
if (o == null) {
for (int i = size - 1; i >= 0; i--) {
if (elements[i] == null) return i;
}
} else {
for (int i = size - 1; i >= 0; i--) {
if (o.equals(elements[i])) return i;
}
}
return -1;
}
/**
* 判断线性表中是否包含元素
*
* @return 如果没有元素, 返回true; 否则返回false
*/
@Override
public boolean isEmpty() {
return size == 0;
}
/**
* 删除指定索引位置的元素
*
* @param index 指定索引位置
* @return 被删除的元素
*/
@Override
@SuppressWarnings("unchecked")
public E remove(int index) {
checkIndex(index);
E removeValue = (E) elements[index];
for (int i = index; i < size - 1; i++) {
elements[i] = elements[i + 1];
}
elements[size - 1] = null; // 为了避免内存泄漏
size--;
modCount++;
return removeValue;
}
/**
* 删除第一个与指定对象o相等的元素
*
* @param o 指定对象
* @return 如果删除成功返回true, 否则返回false
*/
@Override
public boolean remove(Object o) {
int index = indexOf(o);
if (index != -1) {
remove(index);
return true;
}
return false;
}
/**
* 替换指定索引位置的元素
*
* @param index 指定索引位置
* @param e 新值
* @return 旧值
*/
@Override
@SuppressWarnings("unchecked")
public E set(int index, E e) {
checkIndex(index);
E oldValue = (E) elements[index];
elements[index] = e;
return oldValue;
}
/**
* 获取线性表中元素的个数
*
* @return 性表中元素的个数
*/
@Override
public int size() {
return size;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("[");
for (int i = 0; i < size; i++) {
sb.append(elements[i]).append(", ");
}
if (size > 0) sb.delete(sb.length() - 2, sb.length());
return sb.append("]").toString();
}
/**
* 返回一个迭代器, 光标后面的元素的索引为 0
*
* @return 迭代器
*/
@Override
public MyIterator<E> iterator() {
return new Itr();
}
/**
* 返回一个迭代器, 光标后面的元素的索引为 index
*
* @param index 光标后面的元素的索引
* @return 迭代器
*/
@Override
public MyIterator<E> iterator(int index) {
checkIndexForAdd(index);
return new Itr(index);
}
private class Itr implements MyIterator<E> {
// 属性
int cursor; // 下一个元素的索引
int expModCount = modCount;
int lastRet = -1; // 最近返回元素的索引,-1表示最近没有返回元素, 或者是最近返回的元素失效了
// 构造方法
Itr() {
}
Itr(int index) {
cursor = index;
}
/**
* 判断光标后面是否有元素
*
* @return 如果光标后面还有元素返回true, 否则返回false
*/
@Override
public boolean hasNext() {
return cursor != size;
}
/**
* 将光标往后移动一个位置, 并将越过的元素返回
*
* @return 被光标越过的元素
*/
@Override
@SuppressWarnings("unchecked")
public E next() {
// 判断迭代器是否失效
checkConModException();
if (!hasNext()) {
throw new NoSuchElementException();
}
/*E retValue = (E) elements[cursor];
lastRet = cursor;
cursor++;
return retValue;*/
lastRet = cursor;
return (E) elements[cursor++];
}
private void checkConModException() {
if (expModCount != modCount) {
throw new ConcurrentModificationException();
}
}
/**
* 判断光标前面是否有元素
*
* @return 如果光标前面是有元素返回true, 否则返回false
*/
@Override
public boolean hasPrevious() {
return cursor != 0;
}
/**
* 将光标往前移动一个位置, 并把被光标越过的元素返回
*
* @return 被光标越过的元素
*/
@Override
@SuppressWarnings("unchecked")
public E previous() {
checkConModException();
if (!hasPrevious()) {
throw new NoSuchElementException();
}
/*cursor--;
E retValue = (E)elements[cursor];
lastRet = cursor;
return retValue;*/
lastRet = --cursor;
return (E) elements[cursor];
}
/**
* 获取光标后面元素的索引
*
* @return 光标后面元素的索引
*/
@Override
public int nextIndex() {
return cursor;
}
/**
* 获取光标前面元素的索引
*
* @return 光标前面元素的索引
*/
@Override
public int previousIndex() {
return cursor - 1;
}
/**
* 在光标后面添加元素
*
* @param e 待添加的元素
*/
@Override
public void add(E e) {
checkConModException();
// 如何复用MyArrayList的add(int index, E e)方法呢?
MyArrayList.this.add(cursor, e);
expModCount = modCount;
lastRet = -1;
cursor++; // 保证插入的顺序与存储的顺序一致
}
/**
* 删除最近返回的元素
*/
@Override
public void remove() {
checkConModException();
if (lastRet == -1) {
throw new IllegalStateException();
}
MyArrayList.this.remove(lastRet);
expModCount = modCount;
// 如何移动cursor呢?
cursor = lastRet; // Caution!
lastRet = -1;
}
/**
* 替换最近返回的元素
*
* @param e 新值
*/
@Override
public void set(E e) {
checkConModException();
if (lastRet == -1) {
throw new IllegalStateException();
}
elements[lastRet] = e;
lastRet = -1;
}
}
MyIterator迭代器
import java.util.Iterator;
public interface MyIterator<E> extends Iterator<E> {
void add(E e);
boolean hasNext();
boolean hasPrevious();
E next();
int nextIndex();
E previous();
int previousIndex();
void remove();
void set(E e);
}
MyList链表
public interface MyList<E> extends Iterable<E> {
boolean add(E e);
void add(int index, E element);
void clear();
boolean contains(Object o);
E get(int index);
int indexOf(Object o);
int lastIndexOf(Object o);
boolean isEmpty();
MyIterator<E> iterator();
MyIterator<E> iterator(int index);
E remove(int index);
boolean remove(Object o);
E set(int index, E element);
int size();
}
ArrayListOverflowException
public class ArrayListOverflowException extends RuntimeException{
public ArrayListOverflowException() {
}
public ArrayListOverflowException(String message) {
super(message);
}
}