Java集合框架概述
集合可以看作是一种容器,用来存储对象信息。所有集合类都位于java.util包下,但支持多线程的集合类位于java.util.concurrent包下。
一: 集合框架特点介绍
1.集合的概念
JavaAPI所提供的一系列类的实例,可以用来动态的存放多个对象。
Java集合框架提供了一套性能优良,使用方便的接口和类,位于java.util包中。
集合的特点:
长度不固定,只能存储引用类型的对象。
特点:代表一组任意类型的对象,无序,无下标,不能重复
2.集合与数组的区别
集合 |
数组 |
|
长度 |
长度可变 |
长度不可变 |
存储内容 |
可以存储不同类型的数据 |
只能存储同一类型的数据 |
数据类型 |
只能存储引用数据类型 |
可以存储基本数据类型和引用数据类型 |
3.集合框架图

二: collection接口
1.collection特点:
部分集合实现是有序的,部分集合实现是无序的(set)。这里的有序指的(List)是存储的顺序
部分集合实现是可排序的(SortedSet),部分集合实现是不可排序的
部分集合是可重复的(List),部分是**不可重复(Set)**的
1.1.collection常用方法:

//多态 new一个接口的实现类给这个引用
//ArrayList 实现了List接口类,而List继承了Collection父类
// 多态的思想 一个对象的实际类型是确定的,但可以指向对象的引用的类型(父类或有关系的类)
Collection collection = new ArrayList();
//添加
collection.add("小明");
collection.add("小红");
collection.add(1);//这里的1是由基本数据类型自动装箱转换成了包装类
collection.add(true);
//删除
collection.remove("小明");
//collection.removeAll(collection);//删除全部
//修改 在Collection接口中没有提供直接修改的方法,如果要修改那么可以先删除在新增
collection.remove("小红");
collection.add("小李");
//循环遍历功能
Object[] objects = collection.toArray();
for (Object object : objects) {
System.out.println(object);
}
//判断功能
System.out.println(collection.contains("小李"));//true
System.out.println(collection.contains("小李子"));//false
System.out.println(collection.isEmpty()); //判断是否为空
//其他功能
System.out.println(collection.size());//获取集合元素个数
2.iterator接口
集合上的迭代器。实现了collection接口的集合类都有一个iterator(),该方法返回一个iterator接口对象,用来遍历对集合中的数据进行遍历
boolean hasNext()
//返回 true如果迭代具有更多的元素。
E next()
//返回迭代中的下一个元素。
default void remove()
//从基础集合中移除这个迭代器返回的最后一个元素(可选操作)。
2.1.hasNext()方法

Collection cl = new ArrayList<>();
cl.add("张三1");
cl.add("张三2");
cl.add("张三3");
cl.add("张三4");
Iterator iterator = cl.iterator();
//hasNext 判断索引(游标)右边是否有元素
//next(),返回索引右边的的元素,并将索引移动到下一个位置
while (iterator.hasNext()){//判断是否有下一个元素
//条件成立 获取下一个元素并移动游标位置
System.out.print(iterator.next());
//张三1张三2张三3张三4
}
2.2.remove方法
public static void main(String[] args) {
Collection cl = new ArrayList<>();
cl.add("张三1");
cl.add("张三2");
cl.add("张三3");
cl.add("张三4");
Iterator iterator = cl.iterator();
while (iterator.hasNext()){//判断是否有下一个元素
//条件成立 获取下一个元素并移动游标位置
iterator.next();
iterator.remove();//移除游标左侧的元素 必须先移动下标在执行删除
}
System.out.println(cl);
}
3.foreach循环
在collection集合中我们可以使用foreach循环来实现遍历集合中的元素
Collection cl = new ArrayList<>();
cl.add("张三1");
cl.add("张三2");
cl.add("张三3");
cl.add("张三4");
Iterator iterator = cl.iterator();
for (Object o:cl){
System.out.println(o);
}
三: list接口
1.List概念介绍
List集合代表一个有序、可重复集合,集合中每个元素都有其对应的顺序索引。List集合默认按照元素的添加顺序设置元素的索引,可以通过索引(类似数组的下标)来访问指定位置的集合元素。
List接口是Collection接口子接口
实现List接口的集合主要有:ArrayList、LinkedList、Vector、Stack。
2.List常用方法
2.1常用增删改查方法
List list = new ArrayList();
//添加 可添加重复的和null数据
list.add(1);
list.add(1);
list.add(null);
//list接口新增的方法 add(int index, E element) addAll(int index, Collection<? extends E> c)
//添加指定位置元素 超出list两个元素 会报错
//list.add(4, 1);//IndexOutOfBoundsException
list.add(3, 1);
System.out.println(list);
//list根据下标删除方法 删除
list.remove(1);
//list根据下标修改方法
list.set(0, 2);
//通过获取下标值遍历list
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
2.2其他方法
根据值获取所在的索引值
List list = new ArrayList();
list.add(1);
list.add(2);
list.add("张三");
list.add("李四");
list.add("王五");
list.add(1);
//indexOf 根据值获取第一个出现的索引值 未找到返回-1
System.out.println(list.indexOf(1));
//lastIndexOf 根据值获取最后一次出现的索引值 未找到返回-1
System.out.println(list.lastIndexOf(1));
//subList获取指定索引区间的值 超出索引值报IndexOutOfBoundsException异常
System.out.println(list.subList(1,8));
3.ListIterator接口
ListIterator在util包下继承了Iterator类拥有Iterator类公共方法
在Iterator正向迭代的基础上拓展了逆向迭代
List list = new ArrayList();
list.add(1);
list.add(2);
list.add("张三");
list.add("李四");
//获取ListIterator接口实例
ListIterator iterator = list.listIterator();
//正向迭代判断是否有下一个元素
while (iterator.hasNext()){
//nextIndex:获取游标下一个元素的索引值 next:返回游标右边的值,并将右边移动到下一位
System.out.print(iterator.nextIndex()+":"+iterator.next());
//0:1 1:2 2:张三 3:李四
}
//逆向迭代,判断上一位是否有元素
while (iterator.hasPrevious()){
//previousIndex:获取游标左边元素索引 previous:返回左边索引值,并向左移动
System.out.print(iterator.previousIndex()+":"+iterator.previous());
//3:李四 2:张三 1:2 0:1
}
4.List接口的相关实现类
4.1ArrayList
ArrayList是一个动态数组,也是我们最常用的集合,是List类的典型实现。它允许任何符合规则的元素插入甚至包括null。每一个ArrayList都有一个初始容量(10),该容量代表了数组的大小。随着容器中的元素不断增加,容器的大小也会随着增加。在每次向容器中增加元素的同时都会进行容量检查,当快溢出时,就会进行扩容操作。所以如果我们明确所插入元素的多少,最好指定一个初始容量值,避免过多的进行扩容操作而浪费时间、效率。
ArrayList擅长于随机访问。同时ArrayList是非同步的 。
4.1.1 ArrayList特点
底层的数据结构是数组
能够存储null值
线程不安全,但是效率高
底层是数组结构,那么查询和修改的效率高,增加和删除的效率就低了
有索引,能够方便的检索
元素是可以重复的,我们可自己去重
不可以排序
注意:Arraylist中常用的方法都来自于父类Collection、List、Object。
4.1.2 ArrayList原理分析
1.默认属性
/**
*集合默认容量
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* 空数组
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* 默认容量为空的数组
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* 集合中真实存储数据的数组
*/
transient Object[] elementData; // non-private to simplify nested class access
/**
* 集合中元素的的个数,注意 不是数组的长度
*/
private int size;
2.构造方法
无参构造:创建了一个空的数组
ArrayList list = new ArrayList();
/**ArrayList()源码
* 构造一个初始容量为10的空列表
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
有参构造:创建了一个指定容量的数组
ArrayList list = new ArrayList(20);
/**ArrayList(20)源码
1.构造具有指定初始容量的空列表
2.如果指定初始容量是负的,则抛出IllegalArgumentException异常
*/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
3.add()方法
ArrayList list = new ArrayList();
list.add(10);
/**add源码
*将指定的元素附加到此列表的末尾。
*/
public boolean add(E e) {
//确认内部容量
ensureCapacityInternal(size + 1);
//将要添加的元素放在数组的下一个
elementData[size++] = e;
return true;
}
第一步.ensureCapacityInternal确保内部容量 方法源码
private void ensureCapacityInternal(int minCapacity) {
//{} {}
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//1 10 1
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
//明确数组的容量
ensureExplicitCapacity(minCapacity);
}
第二步.ensureExplicitCapacity明确数组的容量 方法源码
private void ensureExplicitCapacity(int minCapacity) {
modCount++;//记录我对当前集合操作的次数
// 10-0 > 0
if (minCapacity - elementData.length > 0)
//进行扩容
grow(minCapacity);
}
第三步.grow扩容方法源码
/**
* 增加容量以确保它至少可以容纳由最小容量参数指定的元素数量。
*/
private void grow(int minCapacity) {
// 原来的容量 0
int oldCapacity = elementData.length;
//新的容量 0
int newCapacity = oldCapacity + (oldCapacity >> 1);
//新容量 0 - 最小容量10 < 0
if (newCapacity - minCapacity < 0)
//新容量 = 10
newCapacity = minCapacity;
//新容量 10 - 数组最大值 21亿 > 0
if (newCapacity - MAX_ARRAY_SIZE > 0)
//将把Intger容量大小(2的31立方)付给它