集合类的区别和使用

本文把讨论范围限定在List、Set和Queue上,并不包含Map以及并发包下面的集合框架。

一、基础知识

  • 理清楚继承关系,所有的集合类都是实现了Collection这个顶级接口,具体的继承关系如下图所示:
集合类的区别和使用_第1张图片
集合框架的继承关系图
  • List是有序集合,Set是不允许元素重复的集合,Queue/Deque是支持队列特定操作的集合;这些集合的通用操作都被抽象到了Abstract类中;

  • List主要包含Vector、Stack、ArrayList、LinkedList,其中Vector是线程安全的数组列表,性能较低,扩容幅度为100%;Stack是在Vector基础上实现了支持栈的特定操作的集合;ArrayList则是最常用的数组列表,但不是线程安全的,性能比Vector更高,扩容幅度为50%;LikedList则是一个双向链表,非数组结构,理论上没有空间限制;

  • 数组链表非常适合随机访问,除了在头节点和尾节点插入数据之外,其它位置插入数据的性能较差;双向链表则是非常适合在任意位置插入数据,但是不能随机访问,所以查找元素的性能较差;

  • Set主要包含TreeSet、HashSet、LinkedHashSet,其中TreeSet是有序存放的(底层使用的是TreeMap,数据结构是红黑树),会按照元素的排序规则进行有序的存储,因此查找、插入、删除时效率会比较低效;HashSet是按照哈希散列来定位存储位置的(底层使用的是HashMap,数据结构是哈希表),因此查找、插入、删除比较快速(常量级),但是是无序存放的;LinkedHashSet是在HashSet的基础上,增加了一个双向链表,用来记录元素的插入顺序,因此在查找、插入、删除上比HashSet稍慢,需要维护双向链表信息,但是方便按照插入顺序进行遍历;

  • Queue是一种FIFO操作受限的数据结构;Deque是一种双端队列,可以在首尾进行元素的添加和删除操作;

二、进阶知识

  • 除了concurrent包提供的线程安全的集合框架外,我们还可以使用Collections工具类来创建线程安全的集合框架。

        public static void main(String[] args) {
            List list = Collections.synchronizedList(new ArrayList<>());
        }
    

    这种方式创建的集合框架,其实是Collections工具类中的内部类SynchronizedCollection,其中的方法逻辑都是有加上synchronized的,因此来确保线程安全。

  • Java采用的排序算法

    • 首先要掌握基本的八大排序算法及其各自特点和使用场景,还需要知道一些常用的高级排序算法(树、堆、拓扑排序等),除此之外,面对海量数据该使用什么排序方式,关于这些知识点可以参考八种基本排序算法的使用和其它一些文章内容。
    • Java中的排序有两个,一个是Arrays.sort(),还有一个是Collections.sort(),其实后者底层还是用的前者,所以,说到底,Java就Arrays.sort()一个排序,该排序方式是内部排序,即需要全部加入到内存中进行;
    • 对于基本数据类型的数据列表,现代Java会采用一种叫“双轴快速排序”的算法,本质上是一种改进版的快速排序算法,在Java的早起版本中采用的就是传统的快排;
    • 对于对象类型的数据列表,采用的是“TimSort”,本质上是一种归并和二分插入排序相结合的算法;
    • 现代Java为了配合多处理器的硬件,还引入了并行排序parallelSort的支持,其底层则是使用了并发中的fork/join框架。当处理数据量比较小的时候,并行排序可能效果不明显,甚至不如单线程排序,但是当数据量上万之后,开始显现效率了,数据量越大,效率提升越明显。
    • 排序算法的改进是一个永恒的话题,是一个不断优化的过程,Java随着新版本的发布,会有新的排序算法或者排序方式出来。
  • Java8版本中,集合框架支持lambda和stream,Java对集合框架增加了lambda和stream的支持,都是在Collection中实现的,有了这两个,会极大简化编程代码,提高开发效率。

  • Java9版本中,增加了快速创建集合类的静态方法。在以前的版本中,我们想创建一个新的list,就必须这样写:

        public static void main(String[] args) {
            List list = new ArrayList<>();
            list.add("hello");
            list.add("world");
        }
    

    在大多数情况下,我们只是想创建一个小容量的list,而且后续很少再会改变其中的内容,所以Java9提供了如下的:

    List list = List.of("hello","world");
    

    通过of方法一旦创建好了,list就是不可变的,可以在需要线程安全的场景下放心使用。

你可能感兴趣的:(集合类的区别和使用)