什么是集合
用来存放对象的容器,定义了对多个对象进行操作的常用方法。可实现数组的功能
集合和数组的区别:
- 数组长度固定,集合长度不固定
- 数组可以存储基本类型和引用类型,集合只能存储引用类型
Collection体系结构
Collection父接口
代表一组任意类型的对象,无序、无下标、不能重复
在开发过程中,很少会直接使用Collection接口,因为Collection接口只是一个存储数据的标准,并不能区分存储类型
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Hello{
public static void main(String[] args) {
//Collection是接口无法实例化,只能声明对象,它的子类才可以实例化。可以使用父类接口声明引用变量,但不能使用其实现类独有的方法
Collection collection = new ArrayList();
//add()方法添加元素,如果元素是对象,那只是添加了其引用地址
collection.add("java");
collection.add("python");
collection.add("c++");
//因为集合只能存储引用类型,所以此处默认执行了自动装箱的操作
collection.add(1);
//remove()方法删除元素
collection.remove("c++");
//size()方法查看元素个数
System.out.println(collection.size());
//集合对象可以直接打印,内置了toString()方法
System.out.println(collection);
//两种遍历集合的方法
//1.增强for循环(Collection接口类型没有下标,不能用普通for循环)
//ArrayList对象的元素会被当成Object类型来处理,因此可以存储不同的数据类型
for (Object i : collection){
System.out.println(i);
}
//2.iterator()迭代器方法,返回值是Iterator接口类型
Iterator it = collection.iterator();
//迭代器对象的hasNext()方法先判断集合还有没有元素
while (it.hasNext()){
//next()方法取出元素
System.out.println(it.next());
//如果需要删除元素,只能使用迭代器对象的it.remove()方法
//it.remove();
}
//contains()方法判断元素是否存在
System.out.println(collection.contains("c++"));
//isEmpty()方法判断集合是否为空
System.out.println(collection.isEmpty());
}
}
List子接口
有序、有下标、元素可以重复
拥有Collection接口的所有方法,还有自己的方法,如可指定位置添加的add()方法、get()、listIterator()、subList()方法等
ArrayList实现类
数组结构实现,存储空间连续,查询快,增删慢
运行效率快,线程不安全
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class Hello{
public static void main(String[] args) {
//List list = new ArrayList();也可以
ArrayList list = new ArrayList();
//add()方法可指定位置添加元素
list.add("java");
list.add(0, "python");
list.add("c++");
list.add(1);
//subList()方法截取集合的子集
System.out.println(list.subList(1, 3));
//remove()方法可根据下标或内容删除元素
list.remove(0);
list.remove("c++");
//注意,remove()方法中数字代表的是下标,若要删除的元素本身是数字,则需要转换一下类型
list.remove((Object) 1);
//三种遍历集合的方法
//1.for循环或增强for循环
for (int i = 0; i < list.size(); i++) {
//get()方法根据下标获取元素
System.out.println(list.get(i));
}
//2.iterator()迭代器方法
//3.listIterator()列表迭代器方法,可以向前向后遍历、添加、删除、修改元素
ListIterator li = list.listIterator();
while (li.hasNext()){
//next
System.out.println(li.nextIndex() + ":" + li.next());
}
while (li.hasPrevious()){
System.out.println(li.previousIndex() + ":" + li.previous());
}
//indexOf()方法获取元素的下标
System.out.println(list.indexOf("java"));
}
}
拓展:ArrayList源码分析
//ArrayList()
//集合默认是容量为10
private static final int DEFAULT_CAPACITY = 10;
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//如果没有添加任何元素,容量为0;添加一个元素之后,容量变成10
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
//add()
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
//每次扩容,容量增大1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
LinkedList实现类
双向链表结构实现,存储空间不连续,增删快,查询慢
拓展:LinkedList源码分析
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
private static class Node<E> {
//item是实际数据
E item;
//next是下一个节点
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}