一.集合
Java集合类存放于 java.util 包中,是一个用来存放对象的容器
- 集合只能存放对象。比如存一个int型数据1放入集合中,其实它是自动转换成Integer 类后存入的(装箱操作),Java中每一种基本类型都有对应的引用类型
- 集合存放的是多个对象的引用,对象本身还是放在堆内存中
- 集合可以存放不同类型,不限数量的数据类型。定义集合变量时如果不指定数据类型,则默认数据类型为Object
### 数组和集合的比较
针对Java中的数组定长,Java提出了集合框架,实现了一种变长存储数据的容器---集合
数组不是面向对象的,存在明显的缺陷,集合弥补了数组的缺点,比数组更灵活更实用,而且不同的集合框架类可适用不同场合。如下:
- 数组能存放基本数据类型和对象,而集合类存放的都是对象的引用,而非对象本身
- 数组容量固定无法动态改变,集合类容量动态改变
- 数组无法判断其中实际存有多少元素,length只告诉了数组的容量,而集合的size()
可以确切知道元素的个数
- 集合有多种实现方式和不同适用场合,不像数组仅采用顺序表方式
- 集合以类的形式存在,具有封装、继承、多态等类的特性,通过简单的方法和属性即可实现各种复杂操作,大大提高了软件的开发效率
Iterator迭代器
Iterator迭代器:走访器,可以理解为集合中元素的指针
它是Java集合的顶层接口(不包括map系列的集合,Map接口是map系列集合的顶层接口)
public interface Iterator<E> {
boolean hasNext(); 判断是否有后续元素
E next(); 指针向后移动,同时返回指向的数据
default void remove() { 删除指针所指向的元素
throw new UnsupportedOperationException("remove");
}
使用lambda表达式的方式遍历所有元素
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
Iterable接口用以表示实现类是可以迭代的
Iterator<T> iterator();
二.Collection,List,Set接口
Collection,List,set的概述
List和set是Collection的子接口
Collection:1).是单例集合的顶层接口,它表示一组对象,这些对象称为collection的元素
2).Java中不提供此接口的任何直接实现,它提供更具体的子接口(如Set和List)实现
3).Collection中的常用方法:
int size();获取集合中的元素个数
boolean contains(Object o) 判断集合中是否有指定的对象,有true没有false。
元素相等是依赖于equals方法实现的
Object[] toArray();将集合转换为Object类型的数组
<T> T[] toArray(T[] a);
String[] arrs=cols.toArray(new String[] {});
boolean add(E e);向集合中新增元素,成功true否则false
boolean remove(Object o);删除指定的元素o,相等判断使用equals
void clear(); 清空集合中的所有元素
4).实现了Iterable接口,Iterable接口表示当前对象是可遍历的,
要求具体实现类中提供了一个遍历器Iterator的实现
Iterator中常用的方法:
boolean hasNext(); 指针指向的位置之后是否还有元素数据,如果有true,否则false
E next();指针后移,同时返回指针指向的数据
void remove(); 删除指针所指向的元素
forEachRemaining(Consumer)使用lambda遍历后续的所有数据
5).Collection集合的特征:
无序 允许重复元素
List集合的特征:
1).有序集合(也称序列),用户可以精确控制列表中每个元素插入的位置。
用户可以通过整数索引访问元素,并搜索列表中的元素
2).List中特有的方法:
E get(int index);按照索引序号获取指定位置上的元素,需要不能越界
E set(int index, E element);修改指定位置上的元素,覆盖
void add(int index, E element);向指定位置上添加元素,原始数据后移
E remove(int index);删除指定位置上的元素,并返回被删除的元素,原始位置上的元素前移
3).List集合的特征
有序【有下标序号】 允许重复元素
4).List接口的三个实现类
ArrayList:数组实现,查询快,增删慢,轻量级;(线程不安全)
LinkedList:双向链表实现,增删快,查询慢 (线程不安全)
Vector:数组实现,重量级 (线程安全、使用少)
Set接口
Set集合的特征:
无序【没有下标序号】 不允许重复元素
3.ArrayList,LinkedList,Vector的区别
相同点:都是List接口的实现类,都是有序集合,都提供搜索、添加或者删除的操作,都提供迭代器以遍历其内容等功能。
不同点:
1).ArrayList 和 Vector都是基于存储元素的Object类型的数组elementData来实现的,而LinkedList是底层是双向链表实现的。
ArrayList 和 Vector它们会在内存中开辟一块连续的内存来存储,由于数据存储是连续的, 因此,它们支持用序号(下标)来访问元素,同时索引数据的速度比较快。但是在插入元素时需要移动容器中的元素,所以对数据的插入操作执行得比较慢。
ArrayList和Vector都有一个初始化的容量的大小,当里面的存储的元素超过这个大小时就需要动态地扩充它们的存储空间。
为了提高程序的效率,每次扩充容量,不是简单地扩充一个存储单元,而是一次增加多个存储单元。
Vector默认扩充为原来的2倍(每次扩充空间的大小是可以设置的),而ArrayList默认扩充为原来的1.5倍(没有提供方法来设置空间扩充的方法)。
ArrayList与Vector最大的区别就是synchronized(同步)的使用,没有一个ArrayList的方法是同步的,而Vector的绝大多数方法(例如add、insert、remove、set、equals、hashcode等)都是直接或者间接同步的,所以Vector是线程安全的,ArrayList不是线程安全的。正式由于Vector提供了线程安全机制,其性能上也要略逊于ArrayList。
2).LinkedList是采用双向列表来实现的,对数据的索引需要从列表头开始遍历,因此用于随机访问则效率比较低。
但是插入元素时不需要对数据进行移动,因此插入效率较高。同时,LinkedList是非线程安全的容器。