数组建立与初始化java
格式:className[] cn = new className[]{};
能够省略{},但必须在[]里代表长度(变量必须提供维度表达式或数组初始值设定项),能够不用new,直接使用{}初始化,数组在建立时指定长度后只能一个一个的填充数组,不能使用{ }填充数组数组
优势:访问效率高安全
缺点:数组长度固定数据结构
数组在方法内能够不初始化(自动初始化,例:int-->0)this
在建立数组时其类型与数组长度固定(编译时检查,这是与其余容器类的不一样之处)线程
可使用length查看数组的长度(这是数组惟一能够调用的)code
数组能够持有基本类型,容器的泛型不能够,可是有自动包装机制对象
数组引用指向堆中真实对象,对象中保存其余对象的引用blog
可变参数列表排序
编译器会把可变参数列表当作数组,因此能够进行foreach,能够对能够参数列表传入数组
Arrays
sort(T[] t); //必须是基本类型或者实现Comparable接口的类型,不然出现异常,基本类型使用快排,引用类型使用稳定归并 asList(T... a); //接收的可变参数,返回的是List接口类型的数据,不能强转为List的其余实现类 fill(); //用指定数据填充整个数组 binarySearch(); //对已排序的数组查找,使用二分查找 copyof(); //拷贝数组,底层使用的是 System.arraycopy(): 浅复制: 复制对象的引用, 比for循环快不少, 由于for循环是对对象自己的拷贝(用于ArrayList数组的扩容), System.arraycopy()方法是native方法, 没法看到源码(应该是C/C++实现的)
建立集合时不跟泛型
编译器检查不出元素的类型,取元素时须要强转,若强转类型不对则报异常
使用Arrays.asList()生成的List
进行add()或delet()操做运行时会出异常,由于Arrays.asList()的底层为数组,长度不可改变
分类
Collection
List
ArrayList LinkedList
queue
map
特色
区别
ArrayList: 底层数据机构为数组, 随机访问较快, 增删操做较慢
LinkedList: 底层数据结构为链表,增删较快,随机访问较慢
ArrayList
随机访问元素较快, 不擅长操做插入删除
add(int index, E element) 将指定的元素插入此列表中的指定位置。
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }
初始化容量: 建立ArrayList时构造器初始化一个空数组, 当使用add()时, 把数组容量变为静态字段 DEFAULT_CAPACITY=10
private static int calculateCapacity(Object[] elementData, int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { return Math.max(DEFAULT_CAPACITY, minCapacity); } return minCapacity; } private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); } private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); }
1.5倍扩容 : 使用System.arraycopy进行扩容,每次扩容oldCapacity >> 1,位运算右移变为oldCapacity的一半,因此扩容为原来的1.5倍
private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); }
remove() 移除指定数据数-----底层使用System.arraycopy进行数据挪移
线程不安全:
List list = Collections.synchronizedList(new ArrayList(...));//进行同步
容量大小和元素个数的关系??-----ArrayList里面有个int size代表当前的元素个数, 每次add元素就会进行size++, 当元素个数等于容量时就会扩容
default关键字(虚拟扩展方法), 能够在接口里对方法实现, List接口实现了sort()方法
Iterator
ArrayList迭代器以下
private class Itr implements Iterator<E> { int cursor; // index of next element to return int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount; public boolean hasNext() { return cursor != size; } @SuppressWarnings("unchecked") public E next() { checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[lastRet = i]; }
不容许在foreach里删除或添加(来自< <阿里巴巴java开发手册> > )
List<String> a = new ArrayList<>(); a.add("1"); a.add("2"); for (String string : a) { if("2".equals(string)) { a.remove(string); } System.out.printlb(String); }
异常: java.util.ConcurrentModificationException
分析:
remove("1")
第一轮: cussor=0,size=2,取出"1"后cussor+1,删除"1"后size=1
第二轮: cussor=1,size=1, 经hasNext()判断结束循环,元素"2"没有获得遍历
remove("2")
第一轮: cussor=0,size=2,取出"1"后cussor+1,size不变
第二轮: cussor=1,size=2, 取出"2"后cussor+1,删除"2"后size=1
第三轮: cussor=2,size=1,hasNext()为true不能结束循环,此时进入next()方法内的checkForComodification()方法就抛出异常
解决:
List<String> list = new ArrayList<>(); list.add("1"); list.add("2"); Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String item = iterator.next(); if (item.equals"2") { iterator.remove(); } }
LinkedList中的链表节点:
private static class Node<E> { E item; Node<E> next; Node<E> prev; Node(Node<E> prev, E element, Node<E> next) { this.item = element; this.next = next; this.prev = prev; } }
方法:
普通增删查: LinkedList的相比于ArrayList通常多First和Last方法
栈: 后进先出
push(): 往栈底(列表最后)压入数据 pop(); 取出栈顶数据(列表开始) peek() 获取列表第一个元素,peekFirst peekLast poll() 获取第一个元素并移除改元素 pollFIrst pollLast