JavaSE 集合类

1. Vector,ArrayList,LinkedList区别

   a.版本号:Vector是 JDK1.0, 后面两个是JDK1.2

   b.底层实现:前两个底层是数组,LinkedList是链表

   c.线程安全:Vector属于线程安全的集合,arrayList,LinkedList线程不安全

// vector的 add(),remove(),get()方法加的 synchronized锁
public synchronized boolean add(E e) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = e;
        return true;
    }

    /**
     * Removes the first occurrence of the specified element in this Vector
     * If the Vector does not contain the element, it is unchanged.  More
     * formally, removes the element with the lowest index i such that
     * {@code (o==null ? get(i)==null : o.equals(get(i)))} (if such
     * an element exists).
     *
     * @param o element to be removed from this Vector, if present
     * @return true if the Vector contained the specified element
     * @since 1.2
     */
    public boolean remove(Object o) {
        return removeElement(o);
    }

    /**
     * Inserts the specified element at the specified position in this Vector.
     * Shifts the element currently at that position (if any) and any
     * subsequent elements to the right (adds one to their indices).
     *
     * @param index index at which the specified element is to be inserted
     * @param element element to be inserted
     * @throws ArrayIndexOutOfBoundsException if the index is out of range
     *         ({@code index < 0 || index > size()})
     * @since 1.2
     */
    public void add(int index, E element) {
        insertElementAt(element, index);
    }

    /**
     * Removes the element at the specified position in this Vector.
     * Shifts any subsequent elements to the left (subtracts one from their
     * indices).  Returns the element that was removed from the Vector.
     *
     * @throws ArrayIndexOutOfBoundsException if the index is out of range
     *         ({@code index < 0 || index >= size()})
     * @param index the index of the element to be removed
     * @return element that was removed
     * @since 1.2
     */
    public synchronized E remove(int index) {
        modCount++;
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);
        E oldValue = elementData(index);

        int numMoved = elementCount - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--elementCount] = null; // Let gc do its work

        return oldValue;
    }

   e:扩容机制:vector2倍扩容,arrayList1.5倍扩容

  2.HashSet(无序存储,实际上就是HashMap):底层为数组

      允许为空,且不能重复,元素乱序存储

      判断重复依据 HashCode() + equals() 

      Object: public native int hashCode():返回对象地址的hash码

      两个对象相等判断:必须hashCode()与equals()均返回为true才认为相等

  3.TreeSet(有序存储):底层为红黑树(平衡二叉树的一种)

       TreeSet不允许为NULL,有序存储

       TreeSet判断重复元素由CompareTo()来实现

       自定义类要想使用TreeSet,必须覆写Comparable接口,无需再覆写 equals(),hashCode()方法

  3.HashTable()

     版本号:JDK 1.0

     HashTable() key,value 均不为空

     线程安全:在增删改查等方法上加锁(synchronized,同Vector)

     Hashtable 存储的内容式键值对(key-value)映射,其底层实现是一个Entry数组+链表

     key,value都不可以为空。此外,Hashtable中的映射不是有序的

     底层是:采用数组+链表来实现的,负载因子设置0.75

  4.  HashMap子类(*****)

     HashMap允许key,value为null,value允许多个为null

     源码解析:

     HashMap内部实现:数组+链表

       数组被分为一个个的桶(bucket),通过hash址决定键值对在数组的寻址;hash相同的键值对,以链表形式存储

       当链表大小超过阈值(TREEIFY_THRESHILD=8),将其树化成(红黑树)

      初始化默认负载因子为 0.75

      HashMap采用lazy_load,在初次使用时对table初始化

      resize() 方法:

                         负责创建初始化存储表格或者在容量不满足需求时扩容

                         初始化时桶大小为16

      HashMap判断何时需要扩容:

      当向容器中添加元素的时候,会判断当前容器的个数,如果大于等于阈值,即大于等于门限值的时候,就要自动扩容了

       a.门限值 = 负载因子 * 容量 (什么时候需要调正容量)

       b.门限值通常以倍数调整(newThr = oldThr << 1),当元素个数超过门限值大小时,调整Map大小

       c. 扩容后将老数组元素拷贝到新数组

   容量和负载因子值的设置:

    容量: public HashMap(int initialCapacity):设置容量

              预设容量大小需要满足 > “预估元素数量/负载因子” 同样是2的幂次方

    负载因子:

                a.不推荐改变,默认负载因子符合通用场景需求

                b. 不要设置超过0.75的值,否则会显著增加Hash冲突,降低 HashMap性能

                c.也不要设置小于0.75的值,否则会引发频繁的扩容,影响访问性能

   树化: JDK1.8 为什么引进树化

              安全问题:当对象的Hash值冲突时,会放在一个桶中以链表的形式存储,链表过程会严重影响存取的性能

              同一个桶中元素个数 > 8,会尝试进行树化

              如果容量小于 MIN_TREEIF_CAPACITY,只会再次调用resize()进行扩容

              如果容量大于 MIN_TREEIF_CAPACITY,才会进行树化改造

   非树化:当链表变为红黑树后,元素删除 n 次后,如果红黑树的节点个数 < UNTREEIF_THRESHOLD(默认为6),在下一次调用resize()后,又会将红黑                     树变为链表

5. HashMap与Hashtable区别

    Hashtable是早期Java类提供的一个哈希表实现的,本身是同步的,不支持null键和值,由于同步导致的性能开销,所以很少被推荐使用

    HashMap JDK1.2主要区别在于HashMap不是同步的,支持null键和值,通常情况下,HashMap进行put或者get操作,可以达到常数时间的性能,所以它是绝大多数利用键值对存取场景的首选

6.ConcurrentHashMap JDK1.7的实现

    a.分离锁。 将内部结构分段 (16个:Segment),存放的HashEntry数组,hash相同的条目也按照链表存储。并发操作的时候,只锁定条目对应的Segment                        段,有效避免类似Hashtable整体同步的问题,大大提高性能

    b. HashEntry内部使用被volatile修饰的value字段来保证内存可见性

         构造时,Segment数量由concurrentcylevel决定,默认为16,必须为2的幂次方

6.1  ConcurrentHashMap JDK1.8实现

       1.总体结构上与HashMap变得非常相似,大的桶数组,内部为链表结构。虽然内部仍有Segment定义,但是无任何结构上的用途

       2.因为不再使用Segment,初始化简单,修改成为 lazy_load,有效避免初始开销

       3.数据存储使用volatile关键字,保证内存可见性

       4.使用CAS操作,在特定场景下使用无锁并发操作

7. Map的遍历: entrySet,迭代器

    a.通过Map.keySet遍历 key 和 value

for(String key : map.keySet()){
    String value = map.get(key);
    System.out.println(key+value);
}

    b.通过 Map.entrySet 使用迭代器 iterator 遍历 key 和 value

Iterator<Map.Entry<String,String>> iterator = 
                                        map.entrySet().iterator();
while(iterator.hasNext()){
    Map.Entry<String,String> entry = iterator.next();
    System.out.println(entry.getKey()+entry.getValue());
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值