Java—ArrayList集合的运用与详解
1.什么是集合类:
集合类是用来存放某类对象的。集合类有一个共同特点,就是它们只容纳对象。这一点和数组不同,数组可以容纳对象和简单数据。集合类容纳的对象都是Object类的实例,一旦把一个对象置入集合类中,它们的类信息将丢失,也就是说,集合类中容纳的都是指向Object类对象的指针。因为Object类是所有类的祖先,所以可以在这些集合中存放任何类而不受限制。
2.为什么使用集合而不是数组?
2.1集合和数组相似点:
都可以存储多个对象,对外作为一个整体的存在
2.2数组的缺点:
长度必须在初始化时指定,并且是固定不变的
数组采用连续在初始化时指定,删除和添加效率低下
数组无法直接保存映射关系
数组缺乏封装,操作繁琐。
3.集合架构的分类
3.1 Collection:线性,可迭代,继承java.lang.Iterable。实现这个接口的类型,必须可迭代,可以使用forEach
3.2 List:接口存储一组不唯一,有序(索引顺序)的对象,有索引查询速度快
3.3 Set:接口存储一组唯一(重写hashCode&equals方法),无序(底层哈希表存储无序)的对象,底层的运行是Map
3.4 SortedSet:可排序的Set,有点像Set和Hash的结合体,和Set一样,它里面的元素是唯一的,类型是是String,所以可以理解为就是一个Set。但是Set里面的元素是无序的,而SortedSet里面的元素都带有一点浮点值,叫做分数,所以这一点和Hash有 点像,因为每个元素都映射到了一个值。
3.5 Map:接口存储一组键值对对象,提供key到value的映射。Key是唯一(必须重写hashCode和equals)、无序。value是不唯一、无序,查询速度快,是根据键(key)查找值(value)
4.List的主要实现类有那些
List:有序、不唯一(可重复)
ArrayList的主要特点:在内存中分配连续的空间,实现了长度可变的数组,遍历元素和随机访问元素的效率较高。添加和删除需要大量移动元素效率低,按照内容查询效率低。在数组容量未超标的时候,末尾增删效率极高。有索引,依据索引查找效率极高。底层数组默认的长度在1.5之前是10,在1.5之后默认的长度为0。
LinkedList的主要特点:采用双向链表存储方式;遍历和随机访问元素效率低下;随机增加、删除元素效率较高(但是前提也是必须先低效率查询才才可以,如果插入删除发生在头尾可以减少查询次数),作为栈或队列使用几率高。
Vector的主要特点:线程安全的ArrayList,所有的方法都是同步的。
package com.bjsxt.test;
import java.util.ArrayList;
import java.util.Iterator;
public class TestArrayList1 {
public static void main(String[] args) {
//创建一个ArrayList对象
ArrayList list = new ArrayList();
ArrayList list1 = new ArrayList();
//向集合中添加元素,这种添加方式是把元素添加到最后的位置,依次的添加。
/**
* add向列表的尾部添加指定的元素,
*/
list1.add("张三");
list1.add("李四");
list1.add("麻子");
//此添加方式是根据指定的索引位置添加元素,把元素添加到指定的位置,底层就会发生元素后移。
list1.add(2,"妞妞");
//输出指定的集合中元素的个数
System.out.println(list.size());
//输出
System.out.println(list);
/**
* 集合的遍历方式有三种
*/
//1.使用普通for循环
System.out.println("Sting普通for循环");
for (int i = 0; i <list1.size() ; i++) {
//获取第i个元素,get此方法返回值是Object,根据我们所在集合中所添加的元素的类型进行强转。
String elem1 = (String) list1.get(i);
//输出第i个元素
System.out.println(i+" "+elem1);
}
//2.使用增强的for循环
System.out.println("String增强for循环");
for (Object elem1:list1) {
//获取第i个元素
String i = (String) elem1;
System.out.println(i);
}
//3.使用Iterator迭代器
System.out.println("String迭代器");
//获得iterator迭代器
Iterator it1 = list1.iterator();
//还有元素就继续循环,没有就退出循环
while (it1.hasNext()){
//如果有元素就取出来
String elem1 = (String) it1.next();
//输出
System.out.println(elem1);
}
}
}
5.ArrayLis源码解析
ArrayList内部维护了一个Object数组作为属性,add方法在执行时其实就是将元素放入
elementDate这个对象数组中
在源码中的add中(size+1)就是在判断数组容量够不够用,如果在不够用的情况下就会自动的给数组扩容。elememtDate因为是一个Object对象数组,那么也就是说JAVA中任何数据类型的元素都可以存入ArrayList集合中。泛型要求存入的元素数据类型要一致。
1.ArrayList内部维护的数组一开始有多大?
答:早、在使用空参数创建ArrayList时,elementDate赋值为空数组{},空数组长度为0不能够存储数据;但是,当数组中第一次添加数据时,ArrayList会自动的调整elementDate的长度,其实就是再创建一个数组,给elementDate赋值。
计算最小的容量
通过以上代码可以看出:通过判断elementDate是否等于空数组0,在add还未初始化,为增加数据的时候时为0的,当向ArrayList中增加数据的时候elementDate不在为空时返回默认的最大值长度为10。minCapactity返回值等于1
第一次初始化后默认的最大的值为10
在ArrayList中是使用的grow方法对数组惊醒扩容。
在grow方法中可以看到:新的数组长度=旧数组长度+旧数组长度/2第一次初始化数组时,容量是10,后面的每一次扩容,新的容量都是原来容量的1.5倍。