集合工具类之List特点和实现类的详解

Java集合框架的由来:
其实在Java2之前,Java是没有完整的集合框架的。它只有一些简单的可以自扩建的容器类,比如Vector,Stack,Hashtable等。

为什么存在容器类:容器类(集合类)可以存储多个数据,既然数组可以存储多个数据,为什么需要定义容器类呢?

数组的弊端:

1、长度是不可变的,一旦数组初始化之后,长度是固定的;
2、在N个地方需要存储多个数据,都得专门去编写数组的操作方法,如此一来,没有体现DRY原则,代码和功能重复-->封装思想;
3、既然每一个人都要使用到数组类,但是不同的人定义的类名和方法是不同的,实现细节也是参差不齐的,SUN公司就自己定义好了容器类,每一个开发者只管调用即可。


什么是集合框架:
尽管这些容器类非常好用,但是却不能集中和统一管理。集合框架是为表示和操作集合而规定的一种统一的标准的体系结构。任何集合框架都包含三大快内容:
对外的接口接口的实现对集合运算的算法。(底层对应着某一种数据结构和算法)

为什么需要集合框架:
1、
提供功能的复用;
2、使得程序员专注于业务开发,而不是数据结构和算法。


常用的框架接口规范:

集合中存储的对象,称之为集合元素。


常用的集合类:
Set(集):
集合中的对象不安特定的方式排序,不允许元素重复;
List(列表):集合中的对象按照索引位置排序,允许元素重复;
Map(映射):集合中每一个元素都包含一对key和value对象,不允许key对象重复,value对象可以重复。


来看一下集合类的关系图




Vector类存储原理:
看过Vector源码之后,会发现Vector类中有一个Object[]类型数组。

        protected Object[] elementData;


1、表面上数据存储到Vector对象中,其实底层依然是把数据存储到Object数组中;
2、我们发现该数组的元素类型是Object类型,意味着集合中只能存储任意类型的对象。
       集合中只能存储对象,不能存储基本数据类型的值。
       在Java5之前,必须对基本数据类型手动装箱。
          如:v.addElement(Integer.valueOf(123));
       java5开始支持自动装箱操作,
          代码如:v.addElement(123);其实底层依旧是手动装箱;
3、集合类中存储的对象,都存储的是对象的引用。




ArrayList类是Java集合框架出现之后用来取代Vector类的:
    二者底层原理都是基于数组的算法,一模一样。
----------------------------------
区别:
Vector:
所有的方法都使用了synchronized修饰符。(线程安全,但性能较低,适用于多线程环境)
ArrayList:
所有的方法都没有使用了synchronized修饰符。(线程不安全,但性能较高)
       但是即使以后在多线程环境下,我们也不使用Vector类:
          ArrayList list = Collections.synchronizedList(new ArrayList(…));

阅读源代码会发现,Vector类和ArrayList的源代码差异有点大(从设计上考虑的)
有的时候某个方法需要返回一个ArrayList对象:
但是在该方法中,如果一个元素都没有查询到,我们不会返回Null,我们会返回一个空寂对象(没有元素的集合)。
       public ArrayList getAll(){
                 //return Collections.emptyList();//最好的方式
                 return new ArrayList();//但是很多人最直观,最简单选用的方式是这种。
       }

在Java7之前,即使使用new ArrayList()创建对象,一个元素都不存储,但是在堆空间依然初始化了长度为10的Object数组,其实没必要。


从Java7开始优化这个设计,new ArrayList(),其实底层创建的是一个空数组。
         Object[] elementData = new Object[]{};
在第一次调用add方法的时候,才会重新去初始化数组。






LinkedList类是双向链表,单向队列,双向队列,栈的实现类:
LinkedList类实现单向队列和双向队列的接口,自身提高了栈和链表的操作方法。
在LinkedList类中存在很多方法,但是功能都是相同的,LinkedList表示了很多数据结构的实现,每一种数据结构的操作名字不同。

LinkedList类是线程不安全的类,在多线程环境下所保证线程安全:
       ArrayList list = Collections.synchronizedList(new LinkedList (…));

无论是链表还是队列,都特别擅长操作头和尾的节点,在LinkedList中大多数方法都是xxFirst/xxLast的

在LinkedList中存在Object get(int index),表示根据索引位置获取相应的元素。
链表没有索引的概念,本不应该有索引,但是从Java2开始存在了集合框架,让LinkedList类作为List接口的实现类,List中提供了该根据索引查询元素的方法,LinkedList内部类提供了一个变量来当做索引。
该方法要少用,因为LinkedList不擅长做查询操作,擅长做保存和删除操作




List实现类特点和性能分析:

三者共同的特点(共同遵循的规则):
1)
允许元素重复;
2) 记录元素的添加顺序。

Vector类:底层采用数组结构算法,方法都使用了synchronized修饰,线程安全,但性能相对于ArrayList较低;(不用)
ArrayList类:底层采用数组结构算法,方法都没有使用synchronized修饰,线程不安全,但性能相对于Vector较高;
LinkedList类:底层采用了双向链表结构算法,方法没有使用synchronized修饰,线程不安全。

线程安全:如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程时运行的结果是一样的,而且其他变量的值也和预期的是一样的,说明线程就是安全的。


数组结构算法和双向链表结构算法的性能问题:
数组结构算法:插入和删除操作速度低,查询和更改较快;
链表结构算法:没有越界和扩容的概念,插入和删除操作速度快,查询和更改较慢。


对List的简单说明:



使用的选择:

1、Vector类打死不要用即使要用也选择ArrayList类

2、如果删除和插入操作频繁,应该选择LinkedList类;

3、如果查询操作频繁,应该使用ArrayList类;
      在开发中使用ArrayList较多,根据具体的需求环境来做选择。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值