java集合框架

集合框架的继承关系

 

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

唯一且有序 升序

原理: 逻辑结构(二叉树)

物理结构(跳转结构)比根节点大的放右数,比根节点小的放左树,比较的实现使用的就是内部或者外部比较器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值