Java 泛型与集合知识点总结

泛型

泛型的应用

  • 在编译时通过一个标识表示类中某个 属性/方法/参数 的类型
  • 编译时,检查添加元素的类型,提高安全性
  • 减少类型转换的次数,提高效率

泛型的语法

1.泛型的声明

  • 泛型类

    class 类名<K, V> {}

    interface 接口 {}

  • 泛型方法

  • 泛型方法可以定义于普通类或泛型类(区别方法使用泛型)

    public static T getMiddle(T... a) { }

2.泛型的使用

  • 实例化

    在类名后面指定类型参数的值(类型):

    List strList = new ArrayList ();

  • 调用泛型方法

    调用泛型方法时,可以把<具体类型> 放在方法名前面

    类.getMiddle()

泛型使用细节

  • 参数类型只能是引用类型,不能是基本类型

  • 不能创建参数化类型的数组

  • 在给泛型指定具体类型后,可以传入该类型或者其子类类型

  • 没有指定类型是,默认泛型是 Object

  • 静态方法不能使用类的泛型

    静态和类相关,类加载时,对象还没创建,如果静态方法使用了类的泛型,JVM 就无法完成初始化

  • 泛型不具备继承性

    List<Object> list = new ArrayList<String>(); error

通配符

  • : 表示支持任意泛型
  • : 支持A 类及A 类的子类,规定了泛型的上限
  • : 支持A 类及A 类的父类,不限于直接父类,规定了泛型的下限

Todo(待补充)

  • 类型擦除(伪泛型)

集合

集合框架体系

alt

迭代器 Iterator

  • next(), hasNext(), remove()

  • 可以认为Java迭代器位于两元素之间

    当调用next 时,迭代器越过下一个元素,并返回越过的元素的引用,remove方法则删除上一次调用next返回的元素

Collection 接口

  • 有些Collection的实现类可以存放重复元素,有些不可以
  • Collection的实现接口 List 是有序的, Set 是无序的
  • Collection 没有直接的实现子类,是通过它的子接口List 和 Set 来实现的
  • Collection接口的元素遍历方式

    • 1.使用迭代器Iterator
    • 2.增强for循环(简化版的iterator)

List 接口

  • List集合类中元素有序,且可重复
  • List集合支持索引
  • 常用方法
    • void add(int i, E element)
    • void addAll(int i, Collection<? extends E> elements)
    • E remove(int i) //删除指定位置元素并返回该元素
    • E get(int i)
    • E set(int i, E element)
    • int indexOf(Object element)
    • int lastIndexOf(Object element)
  • List 接口的元素的遍历方式

    • 1.iterator迭代器
    • 2.增强for
    • 3.普通for + 索引

List 实现类 ArrayList

  • 底层维护的是一个动态的数组
  • 线程不安全的, Vector与其基本等同,除了Vector是线程安全的
  • 创建和扩容流程 Debug
    • 调用无参构造器时,车市elementData容量为零,第一次添加元素时扩容为10, 若再次扩容,则扩容1.5倍
    • 调用有参构造器时指定容量,则出书elementData容量为所指定的大小,若再次扩容,也是扩容1.5倍

List 实现类 LinkedList

  • 底层维护了一个双向链表
  • LinkedList中维护了两个属性first, last分别指向 首节点和尾节点
  • 添加和删除效率高

Set 接口

  • Set集合类中元素无序,且不允许重复,最多只能有一个null
  • Set集合类不能通过索引获取
  • Set 接口的元素遍历方式

    • iterator 迭代器
    • 增强for

Set接口实现类 HashSet

  • 底层是 HashMap(value 值都为空)
  • 不保证顺序,更具hashcode确定索引
  • 不能有重复元素,且只能有一个null

Set接口实现类 LinkedHashSet

  • 是HashSet子类
  • 底层是LinkedHashMap,维护了一个数组 + 双向链表
  • 根据hashCode确定元素的存储位置,同时使用链表维护元素的次序

Queue 接口

  • 双端队列Deque接口
  • ArrayDeque和LinkedList类实现了Deque接口
  • 常用方法
    • add()
    • offer()

    入队,将给定元素添加到队列的队尾,如果成功就返回true,若队列已满,add会抛出异常,offer会返回false

    • remove()
    • poll()

    出队,若队列不为空,删除并返回队列头的元素,若空队列,remove抛出异常,poll返回null

    • element()
    • peek()

    返回队列头元素但不删除,若空队列,第一个抛出异常,第二个方法返回null

Map 接口

  • Map 与Collection 并列存在,用于保存具有映射关系的元素
  • key 和 value 可以是任意引用类型的数据
  • key不允许重复,value可以重复
  • key和value都可以为null,但key中只能有一个null
  • 常用String类作为key
  • Map 接口元素的遍历方式

    • map.keySet() -> 返回所有的key,再通过map.get(key)获取value
      • 增强for
      • 迭代器
    • 取出所有的values map.values()
      • 增强for
      • 迭代器
    • 通过EntrySet获取 k-v (Map.Entry<K, V>) ==》 Set set = map.entrySet()
      • 增强for
      • 迭代器

      Map.Entry 提供的 getKey() 和 getValue()

Map接口的实现类 HashMap

  • 底层维护的是 数组 + 链表 + 红黑树
  • 线程不安全
  • 若添加相同的Key,会覆盖原来的Value
  • 底层机制 Debug
    • 1.HashMap底层维护了Node类型的数组table,默认为null
    • 2.创建对象是,加载因子初始化为0.75
    • 3.添加Key-Value时,通过Key的哈希值得到在table的索引,判断该索引处是否有元素,若无,直接添加;若有,比较两个Key是否相等,若相等,替换value;若不相等还需要判断是树结构还是链表结构,做出相应处理。如果添加时发现容量不足,需要扩容。
    • 4.第一次添加时table数组初始化容量为16,临界值时12(16*0.75),大于等于临界值时扩容
    • 5.以后在次扩容时table扩容为初始的两倍,临界值也发生改变
    • 6.Java8中,如果一条链表元素超过TREEIFY_THRESHOLD(默认8),并且数组table大于等于MIN_TREEIFY_CAPACITY(默认64)时,将树华为红黑树,如果数组大小不满足,则数组扩容

Map接口的实现类 HashTable

  • 线程安全的
  • Key和Value都不能为null

Map接口的实现类 Properties

  • 继承自HashTable
  • 用于读取.properties配置文件

Collections 工具类

  • 用于操作Set、List、Map等集合的工具类
  • 提供一系列静态方法对集合中元素进行排序、查询和修改等操作