Java集合
Java是一门面向对象的语言,就免不了处理对象。为了方便操作多个对象,那么我们就得把这多个对象存储起来。想要存储多个对象(变量),很容易就能想到一个容器。常用的容器我们知道有–>StringBuffered,数组(虽然有对象数组,但是数组的长度是不可变的!)。所以,Java就为我们提供了集合(Collection)~
数组和集合的区别:
1:长度的区别
- 数组的长度固定
- 集合的长度可变
2:内容不容
- 数组存储的是同一种类型的元素
- 集合可以存储不同类型的元素(但是一般我们不这样干…)
3:元素的数据类型
- 数组可以存储基本数据类型,也可以存储引用类型
- 集合只能存储引用类型(你存储的是简单的int,它会自动装箱成Integer)
Collection的由来:
集合可以存储多个元素,但我们对多个元素也有不同的需求
- 多个元素,不能有相同的
- 多个元素,能够按照某个规则排序
针对不同的需求:java就提供了很多集合类,多个集合类的数据结构不同。但是,结构不重要,重要的是能够存储东西,能够判断,获取
把集合共性的内容不断往上提取,最终形成集合的继承体系---->Collection
迭代器(Iterator)介绍
我们可以发现Collection的源码中继承了Iterable,有iterator()这个方法…返回的是Iterator
Iterator也是一个接口,它只有三个方法:
- hasNext()
- next()
- remove()
Iterator实际上就是在遍历集合,所以说:我们遍历集合(Collection)的元素都可以使用Iterator,至于它的具体实现是以内部类的方式实现的!
List集合有三个子类:
- ArrayList
底层数据结构是数组。线程不安全 - LinkedList
底层数据结构是链表。线程不安全 - Vector
底层数据结构是数组。线程安全
ArrayList底层其实就是一个数组,ArrayList中有扩容这么一个概念,正因为它扩容,所以它能够实现“动态”增长。
add(E e)方法:
- 首先去检查一下数组的容量是否足够
- 扩容到原来的1.5倍
- 第一次扩容后,如果容量还是小于minCapacity,就将容量扩充为minCapacity。
- 足够:直接添加
不足够:扩容
add(int index, E element)方法:
- 检查角标
- 空间检查,如果有需要进行扩容
- 插入元素
扩容相关ArrayList的add方法底层其实都是arraycopy()来实现的,总的来说:arraycopy()还是比较可靠高效的一个方法。
get方法:1、检查角标 2、返回元素
set方法:1、检查角标 2、替代元素 3、返回旧值
remove方法:1、检查角标 2、删除元素 3、计算出需要移动的个数,并移动 4、设置为null,让Gc回收
ArrayList是基于动态数组实现的,在增删时候,需要数组的拷贝复制。
ArrayList的默认初始化容量是10,每次扩容时候增加原先容量的一半,也就是变为原来的1.5倍
删除元素时不会减少容量,若希望减少容量则调用trimToSize()
它不是线程安全的。它能存放null值。
Vector与ArrayList区别
Vector是jdk1.2的类了,比较老旧的一个集合类。Vector底层也是数组,与ArrayList最大的区别就是:同步(线程安全)
在要求非同步的情况下,我们一般都是使用ArrayList来替代Vector的了~
如果想要ArrayList实现同步,可以使用Collections的方法:List list = Collections.synchronizedList(new ArrayList(…));,就可以实现同步了~
还有另一个区别:ArrayList在底层数组不够用时在原来的基础上扩展0.5倍,Vector是扩展1倍。
LinkedList解析
LinkedList底层是双向链表~
add方法实际上就是往链表最后添加元素
set方法和get方法其实差不多,根据下标来判断是从头遍历还是从尾遍历
总结
ArrayList:
- 底层实现是数组
- ArrayList的默认初始化容量是10,每次扩容时候增加原先容量的一半,也就是变为原来的1.5倍
- 在增删时候,需要数组的拷贝复制(navite 方法由C/C++实现)
LinkedList:
- 底层实现是双向链表[双向链表方便实现往前遍历]
Vector:
- 底层是数组,现在已少用,被ArrayList替代,原因有两个:
Vector所有方法都是同步,有性能损失。
Vector初始length是10 超过length时 以100%比率增长,相比于ArrayList更多消耗内存。
总的来说:查询多用ArrayList,增删多用LinkedList。
ArrayList增删慢不是绝对的(在数量大的情况下,已测试):
如果增加元素一直是使用add()(增加到末尾)的话,那是ArrayList要快
一直删除末尾的元素也是ArrayList要快【不用复制移动位置】
至于如果删除的是中间的位置的话,还是ArrayList要快!
但一般来说:增删多还是用LinkedList,因为上面的情况是极端的~