集合框架的继承关系
Collection:
1. 迭代方法 三种
2. 与collections的区别: collections是util的一个工具类
3. 调用了iterable 接口
1. Arraylist
特点:底层是数组实现的可以为空
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
//重要参数
private static final int DEFAULT_CAPACITY = 10;
//初始大小
private int size;
// 有参构造
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
//无参构造
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
//扩容原理
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
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);
}
}
扩容原理(jdk1.8源码和1.7源码的不同)
jdk1.8 elementData初始化为空数组,只有当调用add方法 然后调用扩容方法,才会初始化新的数组大小为10, 并赋值过去。
jdk1.7 为大小为10
2. Vector源码
protected Object[] elementData;
/**
* The number of valid components in this {@code Vector} object.
* Components {@code elementData[0]} through
* {@code elementData[elementCount-1]} are the actual items.
*
* @serial
*/
protected int elementCount;
调用构造器
public Vector() {
this(10);
}
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
扩容方法与ArrayList 不同,是之前的2倍
泛型Generic(Jdk1.5以后使用的)
没有泛型的时候使用集合:一般放进去的都是同一类型的数据,便于管理,所以什么类型都可以存进去不方便
ArrayList<Integer> list = new ArrayList<Integer>;
再放其他类型的不行了。
也改变了增强for循环
3. LinkedList
声明了一个叫node的内部类
transient int size = 0;
transient Node<E> first;
transient Node<E> last;
//Node内部类
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;
}
}
public LinkedList() {
}
public boolean add(E e) {
linkLast(e);
return true;
}
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
底层链表
4. 迭代器
迭代器模式
底层关系
简单概括:ArrayList 实现List接口, List接口实现Collection接口, Collection接口实现Iterable接口;Iterable接口中有方法Itertor,和foreach。itertor接口中有方法next hasnext和remove。
在ArrayList中有一个内部类Itr实现了Iteratable接口中的itertor方法返回Itr一个itertor的实现类,实现了next和hasnext以及remove方法。
//javalang包下的接口
public interface Iterable<T> {
//iterator方法 返回一个Iterator
Iterator<T> iterator();
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
}
//util 包下的接口
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
ArrayList中的具体实现:
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable{
transient Object[] elementData;
private int size;
public Iterator<E> iterator() {
return new Itr();
}
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;
Itr() {}
public boolean hasNext() {
return cursor != size;
}
public E next() {
int i = cursor;
if (i >= size)
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
cursor = i + 1;
return (E) elementData[lastRet = i];
}
}
}
ListIterator
List list = new ArrayList();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
Iterator it = list.iterator();
while(it.hasNext()){
if ("3".equals(it.next())){
list.add("5");
}
}
//报错
/*Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:911)
at java.util.ArrayList$Itr.next(ArrayList.java:861)
at Test03.main(Test03.java:20)*/
原因:迭代器和list同时操作数组导致(ConcurrentModificationException)并发修改异常
但是两个都没有办法完成引入ListIterator
Set
特点:唯一;无序(相对于List来说,但不是随机的,值村)
Hashset
add方法返回boolean 类型的值, 若添加已有的值会返回false;在系统提供的引用类型中是这样的。
若添加的是自定义的类型,不满足唯一的特点了,可以添加重复的
原理(数组+链表= 哈希表)
1.首先调用hashcode方法计算哈希值,如果存放的是Integer类型的数组那么调用的是Integer里面的hashcode方法
//Integer 里面的Hashcode直接返回这个数
public int hashCode() {
return Integer.hashCode(value);
}
2.通过哈希值和一个表达式计算出来这个值对应的存放位置
3. 如果元素计算出来的位置相同,追加链表
(一定要重写hashcode和equals方法,因为自定义的类型没有重写这两个方法,导致能够重复添加)
比较器
String调用了Comparable接口
内部比较器:实现了Comparable接口,重写compareto方法
外部比较器:声明一个比较类,
public interface Comparable<T> {
public int compareTo(T o);
}
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
//重写Comparable方法结果返回int类型的数组
//按位比较字符
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
}
}
5. HashMap
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable {
//默认的数组长度
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
//
static final int MAXIMUM_CAPACITY = 1 << 30;
//负载因子
static final float DEFAULT_LOAD_FACTOR = 0.75f;
//底层主数组
transient Entry<k,v>[] table
//
transient int size;
//数组扩容的界限
int threshold;
public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
this.loadFactor = loadFactor;
this.threshold = tableSizeFor(initialCapacity);
}
}
public HashMap(Map<? extends K, ? extends V> m) {
this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
inflateTable(threshold);
putAllForCreate(m);
}
public V put(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
if (key == null)
return putForNullKey(value);
// 获取key的hash码
int hash = hash(key);
//得到元素在数组中的位置
int i = indexFor(hash, table.length);
//如果放入的位置上有东西就直接放
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
final int hash(Object k) {
//没有直接使用Hashcode,又进行了一个二次散列
//防止出现哈希冲突
int h = hashSeed;
if (0 != h && k instanceof String) {
return sun.misc.Hashing.stringHash32((String) k);
}
h ^= k.hashCode();
//扰动函数,增加不确定性
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
static int indexFor(int h, int length) {
// assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2";
return h & (length-1);
}
void addEntry(int hash, K key, V value, int bucketIndex) {
if ((size >= threshold) && (null != table[bucketIndex])) {
resize(2 * table.length);
hash = (null != key) ? hash(key) : 0;
bucketIndex = indexFor(hash, table.length);
}
createEntry(hash, key, value, bucketIndex);
}
void createEntry(int hash, K key, V value, int bucketIndex) {
Entry<K,V> e = table[bucketIndex];
table[bucketIndex] = new Entry<>(hash, key, value, e);
size++;
}
是Entry类型数组中对应的是Entry类的对象,包含:key,value,hashcode,下一个元素的位置
哈希碰撞:当两个键相同时
核心方法:元素在数组中的索引计算公式:h & (length-1) 等价于 h% length ;原因: 与运算效率高
6. Clone和Cloneable接口
Cloneable接口是空的,但是要是调用clone方法必须继承Cloneable接口,然后重写clone方法。
两个注意点:
1. 如果没有实现接口会出现CloneNotSupportedException的异常。
2. 重写的clone方法必须调用super.clone()方法 位于java.Object类中的。
public Object clone() {
try {
ArrayList<?> v = (ArrayList<?>) super.clone();
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}
public interface Cloneable {
}
//Object中的Clone方法
protected native Object clone() throws CloneNotSupportedException;
Randomaccess接口
标志接口
Serializable接口
7.TreeSet
唯一且有序 升序
原理: 逻辑结构(二叉树)
物理结构(跳转结构)比根节点大的放右数,比根节点小的放左树,比较的实现使用的就是内部或者外部比较器