第二十八、九章:类集框架简介、List集合

28、类集框架简介

  从JDK1.2开始JAVA引入了类集开发框架,所谓的类集指的就是一套动态对象数组的实现方案,在实际的开发中没有任何一项的开发可以离开数组,但是传统的数组实现起来非常的繁琐。而且长度是其致命伤,正是因为长度固定,所以传统数组是不可能大范围使用的,但是我们的开发又不可能离开数组,所以最初就只能依靠一些数据结构来实现动态的数组处理,而其中最重要的两个结构:链表、树,但是面对这些数据结构的实现又不得不面对如下问题:

  数据结构的代码实现困难,对于一般的开发者是无法进行使用的;

  对于链表或二叉树当进行更新处理的时候的维护是非常麻烦的;

  对于链表或二叉树还需要尽可能保证其操作的性能

  正是因为这样的原因,所以JDK1.2开始Java引入了类集,主要功能就是对常见的数据结构进行完整的实现包装,并且提供了一系列的接口与子类来帮助用户减少数据结构所带来的开发困难,但是最初的类集实现由于Java本身技术所限,所以对于数据的控制并不严格,全部采用了Object类型进行数据接收,而在JDK1.5之后由于泛型技术的推广,所以类集本身也得到了良好的改进,可以直接利用泛型保存相同类型的数据,并且随着数据量的不断增加,从JDK1.8开始类集中的实现算法也得到了良好的性能提升。(自己要能说出类集里面采用的性能提升方式是什么,必须要能说出来)

  在整个类集框架里面提供有如下几个核心接口:Collection、List、Set、Map、Iterator、Enumeration、Queue、ListIterator.

Collection接口简介

   java.util.Collection是单值集合操作的最大的父接口,在该接口之中定义所以单值数据的处理操作。

  在进行集合操作处理的时候有两个方法最为常用:【增加】add()、【输出】iterator(),在JDK1.5版本以前Collection只是一个独立的接口,但是从JDK1.5之后提供了有Iterable父接口,并且在JDK1.8之后针对于Iterable接口也得到了一些扩充。另外,在JDK1.2到JDK1.4的时代如果要进行集合的使用往往会直接操作Collection接口,但是从JDK1.5时代开始更多的情况下选择的都是Collection子接口

29、List接口简介

  List是Collection子接口,其最大的特点是允许保存有重复元素数据,该接口的定义如下但是需要清楚的是List子接口对于Collection接口进行了方法扩充。

  但是List本身依然属于一个接口,那么对于接口要想使用则一定要使用子类来完成定义,在List接口有三个子类为【90%】ArrayList、【8%】LinkedList、【2%】Vector

  从JDK1.9开始List子接口里面追加有一些static方法,以方便用户处理。

ArrayList子类

  ArrayList是List子接口使用最多的一个子类,但是这个子类在使用的时候也是有前提要求的,所以本次来对这个类的相关定义以及源代码组成进行分析,在JAVA里面ArrayList定义如下:

  如果以方法的功能为例,那么ArrayList里面操作支持与之前编写的链表形式是非常相似的,但它却不是用链表实现的,通过类名称实际上就已经可以清楚的发现了,ArrayList应该封装的是一个数组。如果现在在进行数据追加的时候发现ArrayList集合里面保存的对象数组的长度不够的时候那么会进行新的数组开辟,同时将就数组中的内容拷贝到新数组中,而后数组的开辟操作

  如果在实例化ArrayList类对象的时候并没有传递初始化的长度,则默认情况下会使用一个空数组,但是如果在进行数据增加的时候发现数组容量不够了。则会判断当前的增长的容量与默认容量的大小,使用较大的一个数值进行新的数组开辟,所以可以得出:

 JDK1.9之后:ArrayList默认的构造只会使用默认的空数组,使用的时候才会开辟数组,默认的开辟长度为10

 JDK1.9之前:ArrayList默认的构造实际上就会默认开辟大小为10的数组

  当ArrayList之中保存的容量不足的时候会采用成倍的方式增长,原始长度为10,那么下次的增长就是20,依次类推,在使用ArrayList子类的时候一定要估算你的数据量会有多少,如果超过了10个,那么使用有参构造方法进行创建,以避免垃圾数组的空间产生。

ArrayList保存自定义类对象

   使用List集合保存了自定义的Member类对象,由于contains()与remove()方法的实现要求是通过对象比较的形式来处理的,所以必须在Member类中实现equals()方法的复写。

LinkedList子类

  List接口里面还有另外一个比较常用的子类:LinkedList,这个类通过名称就知道底层实现是链表形式,基于Node节点实现数据存储关系。

  链表与数组的最大区别在于:链表实现不需要频繁的进行新数组的空间开辟,但是数组在根据索引获取数据时(List接口扩展的get()方法)时间复杂度为O(1),而链表的时间复杂度为O(n)

  LinkedList没有像ArrayList那样可以初始化大小的方法,只有无参构造

  LinkedList封装的就是一个链表实现。

 

面试题:请问ArrayList与LinkedList有什么区别?(至关重要)

  ArrayList是数组实现的集合操作,而LinkedList是链表实现的集合操作;

  在使用List集合中的get()方法根据索引获取数据时,ArrayList的时间复杂度为“O(1)”、而LinkedList时间复杂度为“O(n)”(n为集合长度);

  ArrayList在使用的时候默认的初始化对象数组的大小长度为10,如果空间不足则会采用2倍的形式进行容量的扩充,如果保存大数据量的时候有可能会造成垃圾的产生以及性能的下降,但是这个时候可以使用LinkedList子类保存

Vector子类

  Vector是一个原始古老的程序类这个类是在JDK1.0的时候就提供的,而后到了JDK1.2的时候由于许多的开发者已经习惯使用Vector了,并且许多的系统类也是基于Vector实现的,考虑到其使用的广泛性,所以类集框架将其保存了下来,并且让其实现了List接口。

  Vector类如果使用的是无参构造方法,则一定会默认开辟一个10个长度的数组,而后其余的实现操作与ArrayList是相同的,通过源代码的分析可以发现Vector类之中的操作方法采用的都是synchronized,而ArrayList并没有进行同步处理,所以Vector类之中的方法在多线程访问的时候属于线程安全的,但是性能不如ArrayList高。

原文地址:https://www.cnblogs.com/djlindex/p/11343310.html