集合学习总结(1)

集合学习总结(1)

1.1 集合使用中的选取规则

在开发中,选择什么集合实现类,主要取决于业务操作特点,然后根据集合实现类特性进行选择,分析如下:

  1. 先判断存储的类型(- -组对象[单列]或一 组键值对[双列])
  2. 一组对象[单列]: Collection接口
  • 允许重复: List
    增删多: LinkedList [底层维护了一个双向链表]
    改查多: ArrayList [底层维护Object类型的可变数组]
  • 不允许重复: Set
    无序: HashSet [底层是HashMap ,维护了一个哈希表即(数组+ 链表+红黑树)]
    排序: TreeSet
    插入和取出顺序一致: LinkedHashSet , 维护数组+双向链表
  1. 一-组键值对[双列]: Map
  • 键无序: HashMap [底层是:哈希表jdk7: 数组+链表,jdk8: 数组+链表+红黑树]
  • 键排序: TreeMap
  • 键插入和取出顺序一致: LinkedHashMap
  • 读取文件Properties

1.2 各个集合类型的学习总结

1.2.1 集合的框架体系图

Collection

 

 

 


Map

 

 

 

1.2.2 Collection

  • Collection接口实现类的特点
  1. collection实现于类可以存放多个元素,每个元素可以是Object
  2. 有些Collection的实现类,可以存放重复的元素,有些不可以
  3. 有些Collection的实现类,有些是有序的(List),有些不是有序(Set)
  4. Collection接口没有直接的实现子类,是通过它的子接口Set和List来实现的
  • Collection接口对象的遍历方式
  1. Iterator(迭代器)

迭代器的执行原理

 

 

 

  1. 增强for循环

增强for循环可以替代iterator迭代器,特点:增强for就是简化版的迭代器,只能用于遍历集合和数组

  • 基本语法
    for(元素类型 元素名:集合或者数组名){
    访问元素
    }

1.2.3 List接口和常用方法

List接口是Collection接口的子接口

  1. List集合类中元素有序(即添加顺序和取出顺序一致)、 且可重复
  2. List集合中的每个元素都有其对应的顺序索引,即支持索引
  3. List容器中的元素都对应一 个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素
  4. 实现List接口的类有很多,其中常用的有ArrayList,LinkedList和Vector

List常用方法总结

  • list.add 添加元素
  • void add(int index, Object ele) 在index位置插入ele元素
  • Object get(int index) 获取指定index位置的元素
  • Object remove(int index) 删除指定位置元素,并返回此元素
  • Object set(int index,Object ele) 设定指定index位置元素为ele
  • LIst subList(int fromIndex,int toIndex) 返回从fromIndex到toIndex的子集合

1.2.4 ArrayList

  • ArrayList注意事项
  1. ArrayList可以加入null,并且多个
  2. ArrayList是由数组来实现数据存储的
  3. ArrayList基本等同于Vector ,除了ArrayList是线程不安全(执行效率高),在多线程情况下,不建议使用ArrayList
  • ArrayList底层分析
  1. ArrayList中维护了一个Object类型的数组elementData.
    transient Object[] elementData; //transient表示瞬间,短暂的,表示该属性不会被序列号
  2. 当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍
  3. 如果使用的是指定大小的构造器,则初始elementData容量为指定大小, 如果需要扩容,则直接扩容elementData为1.5倍

1.2.5 Vector

  1. Vector底层也是一 个对象数组,protected Object[] elementData;
  2. Vector是线程同步的,即线程安全,Vector类的操作方法带有synchronized
public synchronized E get(int index) {
    if (index > = elementCount)
        throw new ArrayIndexOutOfBoundsException(index);
    return elementData(index);
}
  1. 在开发中,需要线程同步安全时,考虑使用Vector

ArrayList与Vector比较

 底层结构线程安全(同步)效率扩容倍数
ArrayList 可变数组 不安全,效率高 如果是有参构造1.5倍 如果是无参 第一次10,之后按照1.5倍扩容
Vector 可变数组 安全,效率不高 如果是无参,按照默认10,满后按照2倍数扩容 如果指定大小,则每次都按照两倍扩容

1.2.6 LinkedList

LinkedList介绍

  1. LinkedList底层实现了双向链表和双端队列特点
  2. 可以添加任意元素(元素可以重复),包括null
  3. 线程不安全,没有实现同步

LinkedList底层操作机制

  1. LinkedList底层维护了一个双向链表.
  2. LinkedList中维护了两个属性first和last分别指向首节点和尾节点
  3. 每个节点(Node对象) ,里面又维护了prev、 next、 item三个属性,其中通过prev指向前一一个,通过next指向后一个节点,最终实现双向链表
  4. 所以LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高

 

 

 

遍历方式

        //因为 LinkedList 是 实现了 List 接口, 遍历方式
        System.out.println("===LinkeList 遍历迭代器====");
        Iterator iterator = linkedList.iterator();
        while (iterator.hasNext()) {
            Object next = iterator.next();
            System.out.println("next=" + next);
        }
        System.out.println("===LinkeList 遍历增强 for====");
        for (Object o1 : linkedList) {
            System.out.println("o1=" + o1);
        }
        System.out.println("===LinkeList 遍历普通 for====");
        for (int i = 0; i < linkedList.size(); i++) {
            System.out.println(linkedList.get(i));
        }
  • ArrayList和LinkedList比较
 底层结构增删效率改查效率
ArrayList 可变数组 较低,数组扩容原因 较高
LinkedList 双向链表 较高,通过链表追加 较低

1.2.7 Set接口和常用方法

**Set介绍 **

  1. 无序(添加和取出顺序不一致),没有索引
  2. 不允许重复元素,所以至多一个Null
  3. 常用的接口实现类有HashSet,TreeSet

因为Set和List都是Collection的子接口,所以常用的方法和Collection一样

  • Set接口的遍历方式
    和Collection遍历方式一样,可以使用迭代器和增强for循环,不过Set不能使用索引来获取

1.2.8 HashSet

  1. HashSet实现了Set接口
  2. HashSet实际上是HashMap

     

     

  3. 可以存放Null值,但是只能有一个
  4. HashSet不保证元素是有序的,取决于hash后,再确定索引的结果,即不保证存入顺序和取出顺序一致
  5. 不能有重复的元素/对象

HashSet底层机制说明

  • 分析HashSet底层是HashMap, HashMap底层是(数组+链表+红黑树)
  1. HashSet 底层是HashMap
  2. 添加一个元素时,先得到hash值-会转成->索引值
  3. 找到存储数据表table ,看这个索引位置是否已经存放的有元素
  4. 如果没有,直接加入
  5. 如果有,调用equals比较,如果相同,就放弃添加,如果不相同,则添加到最后
  6. 在Java8中,如果一条链表的元素个数到达TREEIFY_THRESHOLD(默认是8),并且table的大小>=MIN TREEIFY CAPACITY(默认64),就会进行树化(红黑树)

具体的底层源码分析在后面单独总结

  • 分析HashSet的扩容和转成红黑树机制
  1. HashSet底层是HashMap,第一-次添加时,table 数组扩容到16,临界值(threshold)是1 6* 加载因子(loadFactor)是0.75 = 12
  2. 如果table数组使用到了临界值12,就会扩容到16* 2 = 32,新的临界值就是32* 0.75 = 24,依次类推
  3. 在Java8中,如果一条链表的元素个数到达TREEIFY_THRESHOLD(默认是8 ),并且table的大小>=MIN TREEIFY CAPACITY(默认64),就会进行树化(红黑树),否则仍然采用数组扩容机制
posted @ 2022-08-03 17:58  AINIBYM  阅读(45)  评论(0)    收藏  举报