集合框架的内容

集合:有一个或多个确定的元素所构成的整体

框架:规范

一.Collection:是一个接口,是所有集合的父类

Collection提供的方法

1. add(Object o)          addAll(Collection c)          添加元素

2.remove(Object o)            removeAll(Collection c)         删除元素

3. clear()        清空集合

4.contains(Object o)        containsAll(Collection c)        判断集合是否包含某个元素

5.iterator()        判断集合是否包含某个元素

6.isEmpty()        判断集合是否为空

7.size()        集合元素的长度

1.List: 列表,存放可重复有序集合

list提供的方法

1.indexOf()获取重复对象第一次出现的索引位置

2.lastIndexOf()获取重复对象最后一次出现的索引位置

3. subList(intfromIndex, inttoIndex)  返回从索引fromIndex到toIndex的元素集合,包左不包右

1)list的子类

ArrayList

1.动态数组

2.原理:默认初始数组长度为10,长度不够用,按1.5倍扩容,把原长度数组的所有元素复制给扩容之后的数组中

3.特点:遍历元素和随机访问元素的效率比较高

源代码


普通数组:不可变的,内容和长度都是不可变的
ArrayList是一个动态数组
通过构造方法,首先创建一个普通的数组
本质就是普通的数组,默认容量为10,容量不够用的时候进行扩容:
    扩容机制:增加到原长度的1.5倍
             如果容量超过最大值,会有限制(报错或固定到最大值的容量) 
//默认数组的容量为10
private static final int DEFAULT_CAPACITY = 10;
//没有任何元素初始化时,是一个空数组
private static final Object[] EMPTY_ELEMENTDATA = {};
//元素数组
transient Object[] elementData;
//数组中的元素个数
private int size;
//数组存储容量上限
 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
//1.创建一个空数组,只要new ArrayList<>(),就创建空数组
public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
//2.在创建数组时给的数组的容量大小值
 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);
        }
    }
//3.在已经有一个数组的基础上,把这个数组的元素复制给一个新数组,并且在新数组上添加新元素
 public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

//4.add原代码  elementData[size++] = e;
//4.1 把指定元素添加到数组的末尾
public boolean add(E e) {
//首先数组长度为0,添加一个元素,把长度+1
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

//4.2 在添加元素时,如果添加的元素个数小于10,则数组第一次扩容按长度10进行扩容
 private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }
//4.3 判断数组长度和扩容的长度
private void ensureExplicitCapacity(int minCapacity) {
        //修改次数
        modCount++;
        // overflow-conscious code
        //minCapacity=10 ,elementData.length=0
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

//4.4 进行扩容,每次扩容1.5倍
//minCapacity=10
 private void grow(int minCapacity) {
        // overflow-conscious code
        //oldCapacity=0,数组长度
        int oldCapacity = elementData.length;
        //>>:右移运算(/2)
        //再次扩容在原基础数组长度的1.5倍进行扩容
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
        //newCapacity =10
            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);
    }

//5.remove 移除元素
//5.1 通过索引删除元素
public E remove(int index) {
        rangeCheck(index);

        modCount++;
        //返回索引要删除的值
        E oldValue = elementData(index);
        //5.2
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        //把删除之后的数组的最后一个索引置为空null
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }
// 5.2 通过索引返回要删除的元素
E elementData(int index) {
        return (E) elementData[index];
    }

Vector

用法和ArrayList一样,是线程安全的,现在几乎不用

Stack

1.stack是Vector的子类

2.栈:后进先出(LIFO)

3.方法

a. push()        压栈,添加元素,将元素推送到堆栈顶部

b. pop()        移除并返回堆栈的顶部元素

c.peek()        返回堆栈顶部的元素,但不删除它

d.empty()        如果堆栈顶部没有任何内容,则返回true。否则,返回false

e.search()        查找对象是否存在于堆栈中。如果找到该元素,它将从堆栈顶部返回元素的位置。否则,它返回-1。

LinkedList 

1.链表的结构,采用链表存储方式,实现了List接口 和 Deque接口 , 它具备集合和队列的特点

2.原理:每个元素是一个Node内部类,Node类有三个属性:前驱,当前元素,后继。不管什么操作只要调整前驱和后继的连接节点就可以

3.特点:插入、删除元素时效率比较高

源代码


linkedList:链表结构
linkedList里每个元素都是一个Node()
    注:Node是LinkedList内的静态内部类
        包含三个元素:前驱,当前元素,后继
        构造方法:需要的参数(前驱,当前元素,后继)
linkedList里没有默认的长度,初始长度为0.
    每添加一个元素,就是新创建一个Node,并且把新添加Node的前驱指向原最后Node节点
    原最后Node节点的后继指向新添加Node节点,并且新添加Node当做整个list的最后节点。
//属性
//长度大小为0
transient int size = 0;
//第一个结点
transient Node<E> first;
//最后一个结点
transient Node<E> last;

//1.内部类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;
        }
    }

//2.add添加
//2.1 
public boolean add(E e) {
        //向最后添加元素
        linkLast(e);
        return true;
    }
//2.2 
void linkLast(E e) {
        //把最后一个元素用l接收
        final Node<E> l = last;
        //创建添加元素的新节点,新节点的前驱就是最后一个结点,当前元素是要添加的元素,后继没有元素为null
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        //最后节点为空,表示LinkedList中没有节点,链表为空
        if (l == null)
        //新建的结点就为第一个结点,即是后继也是前驱
            first = newNode;
        else
        //表示链表中有元素,即原本最后的元素的后继是新建的结点
            l.next = newNode;
        //长度加1
        size++;
        modCount++;
    }

//3.获取元素
//3.1:通过索引获取元素
public E get(int index) {
        checkElementIndex(index);
        return node(index).item;
    }
//3.2:获取元素,类似于二分查找
Node<E> node(int index) {
        // assert isElementIndex(index);
        //先把长度/2 ,获取中间值,把要找的索引和中间值进行判断,大于找右边,小于找左边
        if (index < (size >> 1)) {
        //用x接收第一个元素
            Node<E> x = first;
        //找后继结点
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {
        //用x接收最后一个元素
            Node<E> x = last;
        //找前驱节点
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }

//4.remove移除
//4.1 通过索引进行移除值
public E remove(int index) {
        checkElementIndex(index);
        return unlink(node(index));
    }
//4.2:找到节点,断开节点连接
E unlink(Node<E> x) {
        // assert x != null;
        //断开节点为x
        final E element = x.item;
        final Node<E> next = x.next;
        final Node<E> prev = x.prev;
        //要移除的元素是第一个结点时,直接把后继结点当做第一个结点
        if (prev == null) {
            first = next;
        } else {
        //如果是其他结点,则把当前节点的前驱节点的后继结点为当前结点的后继结点
            prev.next = next;
            x.prev = null;
        }

        if (next == null) {
            last = prev;
        } else {
            next.prev = prev;
            x.next = null;
        }
        //把元素置为空
        x.item = null;
        size--;
        modCount++;
        //并返回该元素
        return element;
    }

Queue

1.单向队列

2.先进先出(FIFO)

3.方法

a. add()        添加元素

b. offer()       将指定的元素添加此队列(如果立即可行且不会违反容量限制),添加成功返回 true;否则返回 false

c. remove()        获取并移除此队列的头,如果此队列为空,则抛出NoSuchElementException异常

d. poll()        获取并移除此队列的头,如果此队列为空,则返回 null

e. element()        返回头部元素,类表为空抛异常

f. peek()        获取队列的头但不移除此队列的头。如果此队列为空,则返回 null

4.实现方式:

ArrayDeque:数组形式实现

LinkedList:链表形式实现

做同样事情的方法,有两套实现方法。

Deque

1.是Queue的子接口,双向链表/队列。

2.先进先出(FIFO)

3.特点:前后两端都可以操作数据

4.方法:在Queue的方法基础上添加 xxxFirst()和xxxLast()

addFirst()        addLast()        offerFirst(E)      offerLast(E)        getFirst()        getLast        peekFirst ...

*ArrayList和LinkedList的比较*

ArrayList 和 LinkedList区别

1.ArrayList是动态数组,有默认初始容量,并且根据数据的不断增加可以动态增长list的长度 linkedList是链表结构,元素之间以Node形式链接。

2.使用上,ArrayList更适合于查找,LinkedList更适合于插入和删除操作

a.ArrayList是数组结构,每个元素都有固定位置,查找的时候可以直接定向到这个位置 插入/删除操作,每插入或删除一个元素都需要改变后面所有元素的位置。

b.LinkedList是链表结构,元素没有固定位置,是通过前驱和后继连接起来。 插入/删除操作,只需要把当前节点的前驱和后继置为空,调整一下前后节点的连接关系就ok,无需改变更多节点。 由于没有固定位置,查找数据不能直接指向,需要按顺序查找。

2.Set:存放不重复的元素,且无序

set不重复的原因:内部源码是map

内部实现本质就是map,set中的元素充当了map中的键

HashSet 

1.无序,不重复的集合

2.使用的方式与List差不多 HashSet在添加数据的时候,会根据equals方法判断是否为重复数据。

3.HashSet(HashMap)内部结构:

1).HashSet内部实现就是HashMap,元素是Node类型的数组。

2).每个元素都是一个单向链表,数组初始长度为16。

3).插入数据,先比较hashCode值

 a.如果值相等(哈希冲突),使用equals进行内容的比较, i.如果内容相等,当前值为重复值不允许添加 ii.如果内容不同,hashCode%长度,根据模插入到hash桶中。

b.如果hashCode值不相等,hashCode%长度,根据模插入到hash桶中。

4).每个单向链表都可能会有很多个元素,可能会产生哈希热点问题。 每个单向链表如果元素个数超过8个,数据结构就变成了红黑树。 如果单向链表里的元素个数小于6个,数据结构要变回链表。

5).如果整个元组的占用数达到了长度的3/4 (扩容因子默认是0.75), 当前元组要进行扩容(2倍,建议数组的长度是2的n次方)。

4.特点:具有很好的存取和查找性无序,唯一


源代码

//hashSet内部直接 new HashMap
public HashSet() {
        map = new HashMap<>();
    }

TreeSet

1.SortedSet的子类,按照元素的自然顺序进行排序,以树结构进行存储

2.特点:元素无索引,元素唯一,对元素进行排序

  源代码

//TreeSet 内部 new TreeMap
public TreeSet() {
        this(new TreeMap<E,Object>());
    }

二.Map: 是一个接口,存储键值对类型元素的接口

1.map是1.2版本之后出现的,原版本是Dictionary(字典)

2.Map:映射 键值对(key-value) 成对出现,键不能重复。

3.常用的实现类:

1).HashMap:最常用的实现类

2).HashTable:不太常用,一般与HashMap做对比

3).TreeMap:

Map常用方法

put(K key,V value):添加元素,如果有值选择替换(可以添加任何类型,以及用null)

remove(Object key): 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。

get(Object key) 根据指定的键,在Map集合中获取对应的值

boolean containsKey(Object key):判断该集合中是否有此键

Set<K> keySet(): 获取Map集合中所有的键,存储到Set集合中。

Set<Map.Entry<K,V>> entrySet(): 获取到Map集合中所有的键值对对象的集合(Set集合)。

 

HashMap键的唯一、不重复

1.hash:散列,尽量让存储的数据分散存储

2.HashMap:动态数组+链表+红黑树(完美平衡二叉树)的数据结构

3.原理:

a.默认是长度为16的数组,对元素的key取hashCode值,对长度取余,余数是几就进第几桶

b.如果余数相同,会放在相同桶中但是是链表形式

c.如果链表长度达到8,变成红黑树,长度小于6,取消红黑树;

d.如果HashCode值一样,内容也相等,元素的value覆盖原有的value

4.使用:key-value键值对;如果key相同,value值被覆盖;key和value都可以为空

5.线程是不安全的,可以通过Vertor进行设置为线程安全

6.与HashSet不一样的地方就是, HashMap存的是键值对, 而HashSet只用到了键而没有用到value。

7.内部类:Node<Entry<K,V>>

内部类属性          hash         key          value         next

内部类构造方法   Node(hash,key,value,next)


源代码

//1.属性
//默认的初始化容量为16:位运算,速度特别快
// <<:左移表示*2,移4位,乘以4个2=16
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
//最大容量:2的30次方
static final int MAXIMUM_CAPACITY = 1 << 30;
//扩容因子:16*0.75=12,达到12时进行扩容,ArrayList是满了才进行扩容,可以自定义扩容因子
static final float DEFAULT_LOAD_FACTOR = 0.75f;
//树化阈值:达到8进行树化
static final int TREEIFY_THRESHOLD = 8;
//树变链表阈值:6
static final int UNTREEIFY_THRESHOLD = 6;
//最小数化容量:64
static final int MIN_TREEIFY_CAPACITY = 64;
//数组
transient Node<K,V>[] table;

//2.构造方法
//2.1:加载扩容因子,把当前扩容因子置为默认扩容因子
public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR; 
    }
//2.2:自定义数组长度
public HashMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }
//2.3:容量和扩容因子都进行自定义
//2.4:直接传已知map

//3.put()
//3.1 添加key,value  
//onlyIfAbsent中(第四个值):    false:key相同value值不变(忽略)    true:赋值
public V put(K key, V value) {
//3.22 hash值
        return putVal(hash(key), key, value, false, true);
    }
//3.2 table初始数组为null
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
//3.21 把数组给一个变量进行接收
        if ((tab = table) == null || (n = tab.length) == 0)
//3.22 resize()是一个数组类型, 数组长度n=16
            n = (tab = resize()).length;
 //3.22 hash值 :正常hash值对16取余
//(n - 1) & hash = 15 & hash = 1111 & hash(10=1010) = 1010(10)
//hash值是啥就是啥
        if ((p = tab[i = (n - 1) & hash]) == null)
//3.23 判断数组中取余位置是否为空,null表示没有元素
//为空创建Node tab[i]:数组索引位置
            tab[i] = newNode(hash, key, value, null);
        else {
            Node<K,V> e; K k;
//3.26 :当前hash值与上一个值得hash值是否一致   
            if (p.hash == hash &&
//3.27 :当前key值与上一个值得key值是否一致 
                ((k = p.key) == key || (key != null && key.equals(k))))
//3.28:p是上一个key值,完全一样把P给k
                e = p;
//3.29:判断是不是数的结构
            else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
//3.291:key不冲突 & 不是树结构    则为链表
            else {
                for (int binCount = 0; ; ++binCount) {
//判断链表上的最后一个结点位置
                    if ((e = p.next) == null) {
//3.292:在最后一个结点的后继创建一个新节点
                        p.next = newNode(hash, key, value, null);
//3.293:判断是否树化:阈值-1(7)
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
//3.294:树化
                            treeifyBin(tab, hash);
//3.295:跳出循环
                        break;
                    }
//3.31:判断下一个key是否冲突
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
//整个链表循环条件,一直往下找结点,知道为空位置
                    p = e;
                }
            }
            if (e != null) { // existing mapping for key
//原来的value(a)=oldValue 
                V oldValue = e.value;
//!onlyIfAbsent:true 替换
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
//3.24:操作次数
        ++modCount;
//3.25:改变长度:1 threshold:12
        if (++size > threshold)
//3.26:扩容:当size=13>12,进行扩容
            resize();
        afterNodeInsertion(evict);
        return null;
    }

//3.3 == 3.22resize()是一个数组类型
final Node<K,V>[] resize() {
        Node<K,V>[] oldTab = table;
//oldCap:旧容量0    oldTab.length=12
        int oldCap = (oldTab == null) ? 0 : oldTab.length;
//旧阈值:0       oldThr =12
        int oldThr = threshold;
        int newCap, newThr = 0;
        if (oldCap > 0) {
//容错
            if (oldCap >= MAXIMUM_CAPACITY) {
                threshold = Integer.MAX_VALUE;
                return oldTab;
            }
//oldCap =table=16 << newCap =16*2=32
            else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
                     oldCap >= DEFAULT_INITIAL_CAPACITY)
                newThr = oldThr << 1; // double threshold
        }
        else if (oldThr > 0) 
            newCap = oldThr;
        //走
        else {  
        //默认容量赋值:16             
            newCap = DEFAULT_INITIAL_CAPACITY;
        //默认扩容因子:0.75 阈值:newThr =12
            newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
        }
        //不走
        if (newThr == 0) {
            float ft = (float)newCap * loadFactor;
            newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
                      (int)ft : Integer.MAX_VALUE);
        }
        //把阈值赋给全局变量    新阈值:24
        threshold = newThr;
        //创建Node类型的数组,默认长度为16         新长度:32
        @SuppressWarnings({"rawtypes","unchecked"})
            Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
        //变成全局变量
        table = newTab;
        //oldTab ==null 不走
        if (oldTab != null) {
//把原数组的值复制到新的数组中
//oldCap:循环16次,因为原数组长度为16:并不知道12个hash值在哪些位置
            for (int j = 0; j < oldCap; ++j) {
                Node<K,V> e;
//判断所有位置是否为空 数据给e
                if ((e = oldTab[j]) != null) {
//把该位置置为空
                    oldTab[j] = null;
//相当于e是最后一个值
                    if (e.next == null)
//对32取余:找数组位置
                        newTab[e.hash & (newCap - 1)] = e;
                    else if (e instanceof TreeNode)
//树节点
                        ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
                    else { // preserve order
//low:低位
                        Node<K,V> loHead = null, loTail = null;
//high:高位
                        Node<K,V> hiHead = null, hiTail = null;
                        Node<K,V> next;
                        do {
                            next = e.next;
//为了散列:原来数据赋值到新数组中
                            if ((e.hash & oldCap) == 0) {
                                if (loTail == null)
                                    loHead = e;
                                else
                                    loTail.next = e;
                                loTail = e;
                            }
                            else {
                                if (hiTail == null)
                                    hiHead = e;
                                else
                                    hiTail.next = e;
                                hiTail = e;
                            }
                        } while ((e = next) != null);
                        if (loTail != null) {
                            loTail.next = null;
                            newTab[j] = loHead;
                        }
                        if (hiTail != null) {
                            hiTail.next = null;
                            newTab[j + oldCap] = hiHead;
                        }
                    }
                }
            }
        }
        return newTab;
    }
//3.4: 3.22 hash值
static final int hash(Object key) {
        int h;
        //map中key可以为null
// >>>:无符号右移操作    ^:异或操作,再一次进行散列化
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

TreeMap :键唯一,值可以重复,如果键重复了,值就覆盖(不重复


1.是SortedMap的子类,可以按照key进行排序

2.排序的规则按照Comparable和Comparator实现的

3.原理:循环遍历数的每一层,判断key的大小,小的放左侧,大的放右侧

4.内部结构是红黑树, 内部结构: 红黑树(完美平衡二叉树) 在红黑树内不需要做优化

源代码

构造方法
    1.没有参数:使用默认排序规则。
    2.一个参数-Comparator:有已知的自定义比较器,使用这个比较规则。
    3.一个参数-普通的Map:使用默认排序规则,把Map里的数据当做初始数据。
    4.一个参数-SortedMap:使用传递过来的map的Comparator充当当前类的比较器。
普通的方法(增删改查)
    put():
        1.判断有没有自定义的Comparator,如果有使用自定义排序规则,如果没有使用默认培训规则
        2.通过do...while的形式(因为树可能有很多层)判断原节点的key和新节点的key的大小
        3.如果key比原key小,放在左子树;
          如果key与原key相同,节点不变,value值覆盖;
          如果key比原key大,放在右子树。
//1.
public TreeMap(Map<? extends K, ? extends V> m) {
        comparator = null;
        putAll(m);
    }

//2.put方法
public V put(K key, V value) {
//2.1:树节点
        Entry<K,V> t = root;
        if (t == null) {
//2.2:比较器
            compare(key, key); // type (and possibly null) check
//2.3:第一个结点
            root = new Entry<>(key, value, null);
            size = 1;
            modCount++;
            return null;
        }
//2.2:变量,不是第一个元素
        int cmp;
        Entry<K,V> parent;
        // split comparator and comparable paths
//2.3:比较器
        Comparator<? super K> cpr = comparator;
//1:比较器为空
        if (cpr != null) {
            do {
                parent = t;
                cmp = cpr.compare(key, t.key);
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);
            } while (t != null);
        }
        else {
//2.4:key为空抛异常
            if (key == null)
                throw new NullPointerException();
            @SuppressWarnings("unchecked")
//默认比较器
                Comparable<? super K> k = (Comparable<? super K>) key;
//2.5:相当于是二叉搜索树
            do {
                parent = t;
//-1:小于    0:等于    1
                cmp = k.compareTo(t.key);
                if (cmp < 0)
//左子节点=t
                    t = t.left;
                else if (cmp > 0)
//右子节点=t
                    t = t.right;
                else
                    return t.setValue(value);
            } while (t != null);
        }
        Entry<K,V> e = new Entry<>(key, value, parent);
        if (cmp < 0)
            parent.left = e;
        else
            parent.right = e;
        fixAfterInsertion(e);
        size++;
        modCount++;
        return null;
    }

//3.Entry
        内部类
                    Entry<K,V>:代表一个树的节点,也就是一个键值对
                         key:当前节点的键值对的键
                         value:当前节点的键值对的值
                         left:当前节点的左子节点
                         right:当前节点的右子节点
                         parent:当前节点的父节点
                         color:节点的颜色,根节点是黑色节点

HashTable

1.是早期的hashMap,继承Dictionary类

2.是线程安全的

三.Collections / Arrays

算法类,提供了集合的一些常用的方法,算法类就是给集合和数组提供了很多静态的方法,使操作更加简便。

sort(List<T> list):将集合中元素按照默认规则排序

 sort(List<T> list,Comparator<? super T> ):将集合中元素按照指定规则排序

比较器:如果想对列表中的元素进行排序,元素的类必须实现Comparable

          如果想临时使用自定义排序规则,自定义类实现Comparator

shuffle(List<?> list):打乱集合顺序

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值