Java 集合概览

  • 从下图可以看出,在Java中除了以Map结尾的类之外, 其他类都实现了Collection接口。并且,以Map结尾的类都实现了Map接口

  • List、Set、Map三者的区别

    • List:存储的元素是有序的、可重复的
    • Set:存储的元素是无序的、不可重复的
    • Map:使用键值对(kye-value)存储,Key 是无序的、不可重复的,value 是无序的、可重复的,每个键最多映射到一个值
  • 集合底层数据结构

    • List

      • Arraylist: Object[]数组
      • Vector:Object[]数组
      • LinkedList:双向链表(JDK1.6之前为循环链表,JDK1.7取消了循环)
    • Set
      • HashSet(无序,唯一): 基于HashMap实现的,底层采用HashMap来保存元素
      • LinkedHashSet:LinkedHashSetHashSet的子类,并且其内部是通过LinkedHashMap来实现的。有点类似于我们之前说的LinkedHashMap 其内部是基于 HashMap 实现一样,不过还是有一点点区别的
      • TreeSet(有序,唯一): 红黑树(自平衡的排序二叉树)
    • Map
      • HashMapJDK1.8之前HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的(“拉链法”解决冲突)。JDK1.8以后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树,以减少搜索时间
      • LinkedHashMapLinkedHashMap继承自HashMap,所以它的底层仍然是基于拉链式散列结构即由数组和链表或红黑树组成。另外,LinkedHashMap在上面结构的基础上,增加了一条双向链表,使得上面的结构可以保持键值对的插入顺序。同时通过对链表进行相应的操作,实现了访问顺序相关逻辑
      • Hashtable:数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的
      • TreeMap: 红黑树(自平衡的排序二叉树)
  • Iterator: 迭代器,可以对集合进行遍历,但每一个集合内部的数据结构可能是不尽相同的,所以每一个集合存和取都很可能是不一样的,虽然我们可以人为地在每一个类中定义hasNext()next()方法,但这样做会让整个集合体系过于臃肿,于是就有了迭代器

    • 作用: 用来遍历集合用的,它的特点是更加安全,因为它可以确保,在当前遍历的集合元素被更改的时候,就会抛出ConcurrentModificationException异常
    • 使用:
   Map<Integer, String> map = new HashMap<>();
map.put(1, "Java");
map.put(2, "C++");
map.put(3, "PHP");
Iterator<Map.Entry<Integer, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Integer, String> entry = iterator.next();
System.out.println(entry.getKey() + entry.getValue());
}
  • 关于线程不安全的集合及解决方案

    • Arraylist,LinkedList,Hashmap,HashSet,TreeSet,TreeMapPriorityQueue都不是线程安全的
    • 解决方案:使用线程安全的集合
      • ConcurrentHashMap: 可以看作是线程安全的HashMap
      • CopyOnWriteArrayList: 可以看作是线程安全的ArrayList,在读多写少的场合性能非常好,远远好于Vector
      • ConcurrentLinkedQueue: 高效的并发队列,使用链表实现。可以看做一个线程安全的LinkedList,这是一个非阻塞队列
      • BlockingQueue: 这是一个接口,JDK内部通过链表、数组等方式实现了这个接口。表示阻塞队列,非常适合用于作为数据共享的通道
      • ConcurrentSkipListMap: 跳表的实现。这是一个Map,使用跳表的数据结构进行快速查找
  • ArraylistVector的区别

    • ArrayListList的主要实现类,底层使用Object[]存储,适用于频繁的查找工作,线程不安全
    • VectorList的古老实现类,底层使用Object[]存储,线程安全的。
  • ArraylistLinkedList的区别

    • ArrayListLinkedList都是不同步的,也就是不保证线程安全
    • Arraylist底层使用的是Object数组;LinkedList底层使用的是双向链表数据结构(JDK1.6 之前为循环链表,JDK1.7 取消了循环)
    • ArrayList采用数组存储,所以插入和删除元素的时间复杂度受元素位置的影响, LinkedList采用链表存储,所以对于add(E e)方法的插入,删除元素时间复杂度不受元素位置的影响,近似O(1),如果是要在指定位置i插入和删除元素的话((add(int index, E element)) 时间复杂度近似为o(n))因为需要先移动到指定位置再插入
    • LinkedList不支持高效的随机元素访问,而ArrayList支持。快速随机访问就是通过元素的序号快速获取元素对象(对应于get(int index)方法)
    • ArrayList的空间浪费主要体现在list列表的结尾会预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗比 ArrayList更多的空间(因为要存放直接后继和直接前驱以及数据)

    扩展:双向链表和双向循环链表

  • comparable 和 Comparator 的区别

    • comparable接口实际上是出自java.lang包 它有一个compareTo(Object obj)方法用来排序
    • comparator接口实际上是出自java.util包它有一个compare(Object obj1, Object obj2)方法用来排序
  • 无序性和不可重复性的含义

    • 无序性不等于随机性 ,无序性是指存储的数据在底层数组中并非按照数组索引的顺序添加 ,而是根据数据的哈希值决定的
    • 不可重复性是指添加的元素按照 equals()判断时 ,返回 false,需要同时重写 equals()方法和 HashCode()方法
  • HashSetLinkedHashSetTreeSet三者的异同

    • HashSetSet接口的主要实现类 ,HashSet的底层是HashMap,线程不安全的,可以存储null
    • LinkedHashSetHashSet的子类,能够按照添加的顺序遍历
    • TreeSet底层使用红黑树,能够按照添加元素的顺序进行遍历,排序的方式有自然排序和定制排序。
  • HashMapHashtable的区别

    • HashMap是非线程安全的,HashTable是线程安全的,因为HashTable内部的方法基本都经过synchronized修饰
    • 因为线程安全的问题,HashMap要比HashTable效率高一点
    • HashMap可以存储nullkeyvalue,但null作为键只能有一个,null作为值可以有多个;HashTable不允许有null键和null 值,否则会抛出NullPointerException
    • 初始容量大小跟每次扩充容量大小不同:
      • 创建时如果不指定容量初始值,Hashtable默认的初始大小为11,之后每次扩充,容量变为原来的2n+1HashMap默认的初始化大小为 16。之后每次扩充,容量变为原来的2
      • 创建时如果给定了容量初始值,那么Hashtable会直接使用你给定的大小,而HashMap会将其扩充为2的幂次方大小。也就是说HashMap总是使用 2的幂作为哈希表的大小
      • JDK1.8 以后的HashMap在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)(将链表转换成红黑树前会判断,如果当前数组的长度小于64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树,以减少搜索时间。Hashtable没有这样的机制

最新文章

  1. phoenix 开发API系列 目录
  2. MySQL1:MySQL函数汇总
  3. Myeclipse的web工程和Eclipse互相转换
  4. python : jquery实现左侧菜单
  5. iOS Build Setting证书设置
  6. 对现有Hive的大表进行动态分区
  7. 基于GBT28181:SIP协议组件开发-----------第三篇SIP注册流程分析实现
  8. MySQL数据库如何解决大数据量存储问题
  9. Oracle EBS-SQL (WIP-13):检查任务组件未选MRP净值.sql
  10. 关于li标签之间的间隔如何消除!
  11. HTML DOM (文档对象模型)
  12. React + TypeScript:元素引用的传递
  13. AutoStartUtil【打开自启动设置界面】
  14. MVC中 jquery validate 不用submit方式验证表单或单个元素
  15. NoSuchMethodError 问题
  16. 【CF429E】 Points and Segments(欧拉回路)
  17. 快速搭建python程序
  18. Bootstrap Modal 使用remote从远程加载内容
  19. Permutation Bo (数学证明)
  20. Java 反射基础

热门文章

  1. Window下将nginx配置为开机自动启动
  2. Spring中的AOP(二)
  3. Struts2 自定义拦截器时Action无法接收到参数
  4. spring cloud config 配置文件更新
  5. Git安装及配置SSH-Key
  6. Build completed with 1 error and 0 warnings in 20 ms
  7. Spring中使用注解时启用&lt;context:component-scan/&gt;
  8. Erlang模块inet翻译
  9. 部署Redis Cluster 6.0 集群并开启密码认证 和 Redis-cluster-proxy负载
  10. 每日一题 - 剑指 Offer 32 - I. 从上到下打印二叉树