集合与泛型

98 阅读5分钟

4.20 复习回顾

集合 collection

1.集合的使用

ArrayList a = new ArrayList();

2.集合中的API

通用api

添加: a.add()

删除:a.remove()

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

交集:a.retainAll(a1)

并集:a.addAll(a1)

元素数量:a.size()

将集合转为数组:a.toArray();

查询:contains()

3.collection 子接口

3.1list

list接口 通用特点

list 具有有序不唯一的特点

有序:添加顺序排序

不唯一:可以存在相同的元素

因为具有顺序 所以新增了操作下标的API

添加到指定位置 :add(index i);

获取指定位置的元素 : ger(index i);

遍历方式

同时 也拥有了 四种遍历方式

增强 for 普通for 迭代器iterator 还有 专属list的ListIterator

list的三种常用实现类

list里边又下分了几个实现类

分别是: ArrayList、Vectore、LinkedList

ArristList 和 Vector 的相同与不同

先把Arraylist和vector放在一起说

特点 :查询快 增删慢

相同点:

1.Arraylist 和 Vector 底层都是用数据进行存储的

不同 vector 是线程安全的 但效率低

ArrayList 线程不安全 效率高

扩容 规则:

ArrayList 底层数组默认长度是 0

第一次创建对象时 给数组扩容 变为10 之后每次 扩容都是 之前的1.5倍

Vector 底层数组默认长度是10

方式一: capacityIncrement<=0  新的容量 oldCapacity*2
方式一: capacityIncrement>0   新的容量 oldCapacity+capacityIncrement;
list的另一个子类 LinkedList

LinkedList

底层是链表 存储数据 特点 :查询慢 但是增删快

相较于 List 又新增了操作头尾的方法

给 头 尾 添加值 :addFirst() addLast()

获取头尾的值 : getFirst() getLast()

删除头尾 : removeFirst() removeLast()

3.2 set

set是 collection 的另一个 子接口

同样 set也拥有三个 常用实现子类 : HashSet LinkedHashSet TreeSet

set 相较于 collection 没新增的 方法 同样也只有 两种遍历方式 : 增强for 和 迭代器 iterator

set的 实现类 (三种实现类底层其实都是map)
HashSet :底层是 哈希表存储

特点 : 无序(元素排列没有顺序)

唯一 :相同元素只能存在 一个

给 集合添加 自定义类型时:必须重写 equals 和 hashCode 方法

LinkedHashSet : 底层是 哈西表+链表

有序 (元素按添加顺序排列)

唯一 : 相同元素只能存在 一个

给 集合添加 自定义类型时:必须重写 equals 和 hashCode 方法

TreeSet : 底层是 红黑树

特点 : 有序 (比较顺序)

唯一 :相同元素只能存在 一个

给 集合添加 自定义类型时: 自定义类型 继承 comparable接口 制定比较规则

或者 创建比较类 comparator 制定比较规则

集合 map

colleaction 传入的一个数值 map 传入的是一个 键值对

使用方式

与collection 大致相同 存在 一个 key 和 value

特点 :喜新厌旧——— 如果key相同 新的value会替换旧的value

三个实现类

HashMap:
    key: 无序:不是添加顺序 在哈西表内的存储顺序
         唯一: 如果key 相同 新的value 会替换旧的value  喜新厌旧
    value:满足泛型要求即可
    底层: 哈西表
    注意:如果key是自定义类型  那么需要重写 equals hashCode()
LinkedHashMap:
    key:
        有序:添加顺序
        唯一:如果key 相同 新的value 会替换旧的value  喜新厌旧
    value:满足泛型要求即可
    底层: 哈西表+链表
    注意:如果key是自定义类型  那么需要重写 equals hashCode()
 TreeMap:
       key:
        有序:排序顺序
        唯一:如果key 相同 新的value 会替换旧的value  喜新厌旧
    value:满足泛型要求即可
    底层:红黑树
      注意:如果key是自定义类型  那么需要指定比较规则
           TreeMap判断重复的标准 是比较规则返回 0

map的 底层源码

map的存储原理

​
一.创建对象后、实例初始化 ---》 普通成员变量 显示赋值语句  构造器内容
      底层顺序表类型
      transient Node<K,V>[] table;
​
      第一次创建对象时没有给底层数组开辟空间 只是给负载因子 赋值为 0.75f
      this.loadFactor = DEFAULT_LOAD_FACTOR;
​
  二.进行数据存储
    2.0 第一次添加数据
        给底层数组开辟长度为16的数组
        threshold:12
    2.1 第一次添加 key 为null
        存到下标为0的位置
    2.2 非第一次添加 指定位置没有值
         直接添加
    2.3 非第一次添加 指定位置有值 hash相同 key 也相同
         新的value替换旧的vlaue 并将旧的value 返回  喜新厌旧
    2.4 非第一次添加 指定位置有值 hash相同   key不同
          追加到原有节点的下面
          七上八下
          jdk7: 在原有节点的上面添加
          jdk8:追加到原有节点的下面
    2.5 扩容 和树化
        扩容: size > threshold 会扩容  数组长度和阈值扩大到原来的2倍
        树化:
           1. 某个位置节点的数量>=8
           2. 数组长度>=64

HashMap 与 HashTable

相同 : 都是 map接口的实现类

底层都是使用 哈希表进行存储

不同 : HashTable 线程是安全的 但是效率低 HashMap 线程不安全 效率高

key 和value 都不能是null key和 value 都可以是null

创建对象 给数组开辟空间 为 11 不给数组开辟空间


泛型

理解:

好比瓶子 厂家出厂瓶子 我们不知道这个瓶子是用来装什么的 ,因此我们需要给瓶子贴上一个标签 ------这个标签就是泛型

也可以 参考形参来理解

什么地方 可以用到泛型 ?

类:

接口:

方法:

类:
   ArrayList<E>
   HashSet<E>
   HashMap<K,V>
接口:
     List<E>
     Collection<E>
     interface Comparator<T>
方法: 调用方法时才能确定类型的方法
    Collections.addAll(list,"张三","李四");

自定义泛型

自定义泛型类
    class A<T>{}
泛型接口
     interface<T>B{}
泛型方法: 返回值前进行泛型的声明
   [修饰符] <T> 返回值类型 方法名(){
​
   }

泛型的上限与擦除

指定泛型的上限:
    T extends 类型
        T:所能接收的数据类型是 类型以及类型的孩子
        <T extends Number>
         T:所能接收的数据类型是 Number以及类型的Number
​
   T extends 类型 & 接口
       T extends Number & Comparable
         T:所能接收的数据类型 既是Number以及类型的孩子也是 Comparable接口的孩子
泛型的擦除:
    1.如果是一个泛型资源却没有指定泛型 那么使用最高类型 Object
    2.泛型只存在于编译时