掌握常见常用Java集合框架

说到集合框架,下面这张图一定经常会看见

初看这副图,你可能会觉得眼花缭乱,问题不大,本文这就带你去了解这副图。

1.整体感知

  • 从图中可以看出,集合框架主要分为两个类型,CollectionMap , Collection 是一个存储一系列单个对象的容器,Map 是一个图,可以存储 一系列键值对。Collection 有三个子接口 ListSet, Queue

  • 所以集合框架有四种具体的类型:Map, List, Set, Queue

  • List代表了有序可重复集合,可直接根据元素的索引来访问;Set代表无序不可重复集合,只能根据元素本身来访问;Queue是队列集合;Map代表的是存储键值对(key-value)的集合,可根据元素的key来访问value。

2.顶层接口

Iterator Iterable ListIterator

  • 先来看我们经常用到的 Iterator 接口 和它的子接口 ListIterator

​ Iterator 有三个主要方法

  1. hasNext() : 检测集合是否还有下一个元素

  2. next() : 返回迭代器的下一个元素,并更新迭代器的游标(类似指针)

  3. remove() : 将迭代器返回的元素删除

    下面来通过例子来观察一下

    public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(89);list.add(39);list.add(29);list.add(19);list.add(29);Iterator<Integer> it = list.iterator();  //获取迭代器while(it.hasNext()){Integer next = it.next();System.out.print(next + " ");}Iterator<Integer> it2 = list.iterator();while(it2.hasNext()){if(it2.next() < 30){it2.remove();}}System.out.println();Iterator<Integer> it3 = list.iterator();  //获取迭代器while(it3.hasNext()){Integer next = it3.next();System.out.print(next + " ");}
    }
    

    输出结果为

    89 39 29 19 29
    89 39
    

    下面解释一下运行的过程,新建一个ArrayList集合,往里面添加了5个元素,第一次获取迭代器,遍历了集合,第二次获取迭代器,把集合里小于30的数删除,第三次再获取迭代器,再次遍历集合,发现小于30的数都被删除掉了。

  • 下面来看一下ListIterator 接口,具体可以参考:Java 集合中关于Iterator 和ListIterator的详解

    • (1)ListIterator有**add()方法,可以向List中添加对象,而Iterator不能
      (2)ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有
      hasPrevious()previous()**方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。
      (3)ListIterator可以定位当前的索引位置,**nextIndex()previousIndex()**可以实现。Iterator没有此功能。
      (4)都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。Iierator仅能遍历,不能修改。

    • 最后来看一下Iterable接口

      public interface Iterable<T> {Iterator<T> iterator();/*** @since 1.8*/default void forEach(Consumer<? super T> action) {Objects.requireNonNull(action);for (T t : this) {action.accept(t);}}default Spliterator<T> spliterator() {return Spliterators.spliteratorUnknownSize(iterator(), 0);}
      }
      

      可以看到其实里面也提供了Iterator接口,在JDK1.8之后,iterable提供foreach遍历,也就是我们经常用的增强for循环。但究其本质,增强for循环其实底层还是用迭代器遍历。

  • 最后来小结一波

    • Iterator 是最常用的迭代器接口,主要提供了三个方法供我们去操作集合,hasNext(), next(), remove()。

    • ListIterator则可以称的上是Iterator的增强版,但它只可以对list集合操作,在Iterator的基础上,它还提供了add()方法,hasPrevious() 和 previous() 供我们后续遍历list集合,它还可以定位一个元素的索引和修改元素。

    • Iterable则提供了foreach遍历集合的方法。

    3.Map集合

    Map存储的是键值对<key, value> 形式的值, 每个key对应唯一一个value, 所以Map不可以有重复的key值,但存储重复的key值时,会将后来的 value 值覆盖掉原来的value值。也就是这个原因,作为key值得元素都必须重写hashcode()和equals()方法。

    • HashMap 和 HashTable

      HashMap是最常用的一个实现类,当存入元素时,会将key的hashcode转化为数组的索引放入对应的数组位置,查找时以同样的方式查找。

      HashTable一般都用不到了,操作方法和HashMap差不多,但性能比HashMap差,主要是底层实现导致的。HashTable有一个子类叫properties,是一个key和value都是String类型得Map,主要用于读取配置文件。

      两者的区别:

      1. HashTable是线程安全的,HashMap是线程不安全的, HashTable底层实现的时候加了synchronized关键字。
      2. 底层实现时,HashTable是数组+链表,HashMap是数组+链表+红黑树, 具体是当链表长度大于8时会转为红黑树,因为这样查询效率会比原来快。
      3. HashMap可以用null作为key,而HashTable不可以
    • LinkedHashMap

      LinkedHashMap是HashMap的子类,它内部有一条双向链表来维护键值对的次序,维护了Map的迭代顺序,与插入顺序一致,具体可以用来实现LRU缓存策略。

    • TreeMap

      TreeMap有排序的功能,底层是数组+红黑树实现的,每一个键值对是一个树节点,默认按key值排序,因此key值必须实现Comparable接口。迭代的时候输出就是按照key值得默认顺序输出。

      下面来例子演示一下

      public static void main(String[] args) {Map<String, Integer> hashmap = new HashMap<>();hashmap.put("Messi",6);hashmap.put("Ronaldo",5);hashmap.put("Kaka",1);hashmap.put("Modric",1);hashmap.put("Lingard",100);System.out.println("用HashMap:   ");Set<Map.Entry<String, Integer>> set1 = hashmap.entrySet();for(Map.Entry<String, Integer> s: set1){System.out.println(s.getKey() +" "+s.getValue());}Map<String, Integer> linkedHashMap = new LinkedHashMap<>();linkedHashMap.put("Messi",6);linkedHashMap.put("Ronaldo",5);linkedHashMap.put("Kaka",1);linkedHashMap.put("Modric",1);linkedHashMap.put("Lingard",100);System.out.println("用LinkedHashMap: ");Set<Map.Entry<String, Integer>> set2 = linkedHashMap.entrySet();for(Map.Entry<String, Integer> s: set2){System.out.println(s.getKey() +" "+s.getValue());}Map<String,Integer> treeMap = new TreeMap<>();treeMap.put("Messi",6);treeMap.put("Ronaldo",5);treeMap.put("Kaka",1);treeMap.put("Modric",1);treeMap.put("Lingard",100);System.out.println("用TreeMap: ");Set<Map.Entry<String, Integer>> set3 = treeMap.entrySet();for(Map.Entry<String, Integer> s: set3) {System.out.println(s.getKey() + " " + s.getValue());}
      }
      
      用HashMap:
      Ronaldo 5
      Lingard 100
      Modric 1
      Messi 6
      Kaka 1
      用LinkedHashMap:
      Messi 6
      Ronaldo 5
      Kaka 1
      Modric 1
      Lingard 100
      用TreeMap:
      Kaka 1
      Lingard 100
      Messi 6
      Modric 1
      Ronaldo 5
      

      用HashMap会使遍历得时候变得无序,每次遍历得时候可能都会不一样,用LinkedHashMap

      则严格按照添加顺序输出, 用TreeMap时则会将key值排序在输出。

    4.Set集合

    Set集合就是存储一系列不重复得元素,和Map有点像,就是少了value。

    Set集合和基本上差不多,有几个具体得实现类,

    HashSet,是基于HashMap 实现的,

    ** LinkedHashSet ,是基于LinkedHashMap实现的, **

    TreeSet,是基于TreeMap实现的

    操作除了没了value值,和Map差不多,存储的元素都要重写hashcode()和equals()方法。

    5.List集合

    常见的实现有ArrayList, LinkedList, Vector, Stack,

    先说一下Vector和Stack, Stack是vector 的子类,它们都是线程安全的,也正是因为这一点,使得它们现在已经过时了。

    ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。

ArrayList 继承了 AbstractList ,并实现了 List 接口。

ArrayList 新建时默认容量为10,如果快达到了容量,就会有扩容机制将容量扩大到原来的1.5倍,所以如果我们创建ArrayList时知道要存储大小时最好指定一下大小,避免不断扩容而增大开销

LinkedList类似于 ArrayList,底层是用链表实现的,并实现了List, Deque, Cloneable, Serializable

接口,实现了Deque接口,说明Deque可以当作双端队列来使用,也就是说,既可以当作“栈”使用,又可以当作队列使用。

关于两者的区别

以下情况使用 ArrayList :

以下情况使用 LinkedList :

  • 你需要通过循环迭代来访问列表中的某些元素。

  • 需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。

6.Queue集合

主要分为单向队列和双端队列,双端队列就是实现Deque接口,最常见的就是上面所说的LinkedList, 单向队列主要介绍优先队列PriorityQueue。

  • 下面先来看JDK为我们提供的双端队列方法

细心的朋友可能会发现,API为每种操作都提供两种方法,那么它们有什么不同呢,调用不同方法操作失败时,结果也会不同。

失败结果 添加 删除 查找
抛出异常 add() remove() get()
False offer() poll() peek()

实现双端队列的除了LinkedList, 还有ArrayDeque, 两者的区别和LinkedList和ArrayList的区别有点像,都是一个底层是链表,一个是数组。用的不多

  • 最后讲一下单向队列的PriorityQueue

    PriorityQueue是基于优先堆实现的,优先队列,顾名思义它可以根据优先级来进行排序

    要求添加的元素实现Comparable接口,并不可以存NULL值

    下面来个例子演示一下

    先定义了一个Player类,实现Comparable接口,并重写了CompareTo方法

    public static void main(String[] args) {Queue<Player> players = new PriorityQueue<>();Player p1 = new Player("Ronaldo", 93);Player p2 = new Player("Messi",94);Player p3 = new Player("Neymar",92);Player p4 = new Player("lewandovsiki",91);Player p5 = new Player("Lingard",100);players.add(p1);players.add(p2);players.add(p3);players.add(p4);players.add(p5);while (!players.isEmpty()){Player p = players.poll();System.out.println(p);}
    }
    
Player{name='Lingard', ability=100}
Player{name='Messi', ability=94}
Player{name='Ronaldo', ability=93}
Player{name='Neymar', ability=92}
Player{name='lewandovsiki', ability=91}
会发现输出顺序和ability有关,这是因为内部已经根据CompareTo方法排好序了,也就是根据ability为优先级了。

最后献上一个表格来总结一下

实现类 增删复杂度 查复杂度 底层数据结构 线程安全
Vector O(N) O(1) 数组 是(过时)
ArrayList O(N) O(1) 数组
LinkedList O(1) O(N) 双向链表
HashSet O(1) O(1) 数组+链表+红黑树
TreeSet O(logN) O(logN) 红黑树
LinkedHashSet O(1) O(1)~O(N) 数组 + 链表 + 红黑树
ArrayDeque O(N) O(1) 数组
PriorityQueue O(logN) O(logN) 堆(数组实现)
HashTable O(1) / O(N) O(1) / O(N) 数组+链表 是(过时)
HashMap O(1) ~ O(N) O(1) ~ O(N) 数组+链表+红黑树
TreeMap O(logN) O(logN) 数组+红黑树
​HashTable O(1) / O(N) O(1) / O(N) 数组+链表 是(过时)
HashMap O(1) ~ O(N) O(1) ~ O(N) 数组+链表+红黑树
TreeMap O(logN) O(logN) 数组+红黑树

一文掌握常见常用Java集合框架相关推荐

  1. -1-3 java集合框架基础 java集合体系结构 Collection 常用java集合框架 如何选择集合 迭代器 泛型 通配符概念 Properties 集合 迭代器...

    集合又称之为容器存储对象的一种方式 •数组虽然也可以存储对象,但长度是固定的:显然需要可变长度的容器 集合和数组的区别?                 A:长度区别                  ...

  2. Java集合框架之四大接口、常用实现类,java基础面试笔试题

    我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家. 扫描二维码或搜索下图红色VX号,加VX好友,拉你进[程序员面试学习交流群]免费领取.也欢迎各位一起 ...

  3. java arraylist排序_一文读懂Java集合框架

    欢迎关注微信公众号:深入浅出Java源码 概念 Java集合框架为程序员提供了预先包装的数据结构和算法来操纵他们.集合框架被设计成要满足以下几个目标. 该框架必须是高性能的.基本集合(动态数组,链表, ...

  4. 容器(一)剖析面试最常见问题之 Java 集合框架

    转载自https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/collection/Java%E9%9B%86%E5%90%88%E ...

  5. java list有序还是无序_牛批!2w字的Java集合框架面试题精华集(2020最新版),赶紧收藏。...

    一个多月前,作者和一些小伙伴决定做一系列的 Java 知识点常见重要问题的小册,方便用来夯实基础!小册的标准就一个,那就是:取精华,取重点.每一本小册,我们都会充分关注我们所总结的知识点是否达到这个标 ...

  6. Java集合框架使用总结

    Java集合框架使用总结 前言: 本文是对Java集合框架做了一个概括性的解说,目的是对Java集合框架体系有个总体认识,如果你想学习具体的接口和类的使用方法,请参看JavaAPI文档. 一.概述 数 ...

  7. 「Java面试题精华集」1w字的Java集合框架篇(2022最新版)附PDF版

    昨天晚上终于把 Java 集合框架部分的的知识点肝完了,转换成 PDF 一共 25 页,后台回复:"面试突击" 即可免费获取下载地址(同样提供了夜间阅读版本). 集合概述 Java ...

  8. 【Java集合框架】ArrayList类方法简明解析(举例说明)

    本文目录 1.API与Java集合框架 2.ArrayList类方法解析 2.1 add() 2.2 addAll() 2.3 clear() 2.4 clone() 2.5 contains() 2 ...

  9. Java集合框架之fastutil

    fastutil扩展了 Java集合框架,通过提供特定类型的map.set.list和queue,以及小内存占用.快速访问和插入:也提供大(64位)array.set 和 list,以及快速.实用的 ...

最新文章

  1. system.err android.os.NetworkOnmainThreadException 错误解决办法
  2. c语言long long类型赋值
  3. linux 清理指定大小的文件
  4. GoogleAppEngine是什么?
  5. 02 socketserver客户端
  6. ANSIBLE---变量
  7. redis配置文件conf详解
  8. ftp服务器vsftpd配置文件,vsftpd配置文件详解及ftp服务器搭建
  9. Swagger注解生成插件
  10. 三极管原理及特性分析
  11. 点量云流化技术在云游戏和虚拟仿真教学中有啥优势?
  12. 【最大流,最大匹配,最大独立集】2018.6.18 【2018提高组】模拟C组 T3 沙耶的玩偶
  13. mysql表误删回复_MySQL数据库误删恢复
  14. MCE | “神药”二甲双胍后,糖尿病药物研究谁将是下一个顶流?
  15. 将git项目提交到其他的git仓库
  16. 担心基站高辐射?快来看5G建设电磁辐射科普宣传片
  17. 录取为2021年同济大学秋季博士研究生(电子与信息工程学院计算机科学与技术)
  18. git clone 拉取远程仓库
  19. 哈佛女校长给2008年本科毕业生的演讲
  20. 计算机联锁仿真论文,计算机联锁系统仿真平台的研究

热门文章

  1. 毕业5年,腾讯65万,拿到美团、滴滴、快手、阿里offer多少钱
  2. 拼多多API分享:抓取拼多多商品详情页数据
  3. 中国历史上十大经典遗言
  4. 数据仓库(二) 数仓理论(重点核心)
  5. centos linux开始防火墙
  6. 小红书的文案有什么特点
  7. Linux Vi命令使用手册
  8. WPS的JS宏设置页边距方法
  9. 资金安全责任险对个人账户负责?
  10. XML和Schema命名空间详解---实例篇