集合简介
概述
什么是集合呢?集合规范而言是一类引用数据类型。当我们有多个数据需要存储的时候我们一般使用数组来存储。但数组有一个很不讨喜的特点就是数组在初始化的时候其长度就被定死了,不可改变。其存储的数量不变,因此在使用的时候一般用于存储数量不变的场景中。当遇到存储数量需要改变的时候数组就显得不太合适。因此我们引入了集合!
作用
集合,可以保存数量不确定的数据,更重要的是,集合能保存具有映射关系的数据。集合中只能保存对象(对象的引用变量),而数组元素可以是基本数据类型的值,也可以是对象(对象的引用变量)。
集合类
集合类,主要由两个接口派生而来:Collection 和 Map
Collection接口
其子类关系图如下:
Collection 接口派生的子接口:Set 和 List 接口
Java 提供的队列实现:Queue(类似 List)
Collection集合
Collection本身是接口不能实例化对象,我们使用时需要使用向上转型,使用接口接收子类对象来操作Collection接口中特有的方法。
Collection中常用方法
方法 | 作用 |
---|---|
add(Object obj) | 在集合中,添加一个元素 |
addAll(Collection c) | 把集合 c 中的所有元素添加到指定的集合中。 |
clear() | 清除集合中所有元素。 |
contains(Object obj) | 常用于判断集合中是否包含指定元素。 |
containsAll(Collection c) | 常用于判断某集合中是否包含指定的 c 集合中的所有元素。 |
isEmpty() | 判断集合是否为空。 |
iterator() | 获取一个 Iterator 迭代器对象,用来遍历集合里的元素。 |
remove(Object obj) | 删除指定元素 |
removeAll(Collection c) | 在某集合中删除指定 c 集合中包含的所有元素。 |
size() | 获取集合中元素的个数。length() 获取长度 |
toArray() | 把集合转成一个数组,集合元素会变成数组元素。 |
这些常用的方法,都可以通过开发者 API 文档中找到,非常多但不建议死记硬背,无非就是添加对
象、删除对象、清空集合、判断集合是否为空等几个经典动作。建议,初学阶段要多去了解每个方法
的作用,才能更好地知道都有哪些功能将来能用到实际开发中。
演示用例
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionDemo {
public static void main(String[] args) {
//注意导包需要导入java.util包下
//Collection本身是 无序可重复
//向上转型 调用共有的方法和属性 以实现子类ArrayList()为例
Collection c1 = new ArrayList();
Collection c2 = new ArrayList();
//添加 add() 只能添加引用数据类型 因此实际添加的是基本数据类型的包装类类型
c1.add("权力的游戏");
c1.add(true);
c1.add(188);
c1.add(222);
c2.add(16.5);
c2.add(188);
c2.add(222);
//直接添加集合内的数据 addAll
c1.addAll(c2);
//集合内的数据可以直接打印输出
System.out.println(c1);
//集合长度size()
System.out.println(c1.size());
//判断
//判断此集合是否为空 为空返回true
System.out.println(c1.isEmpty());
//判断此元素是否存在于此集合contains() 存在返回true
System.out.println(c1.contains(188));
//判断此是否存在于此集合contains() 存在返回true
System.out.println(c1.containsAll(c2));
//移除单个元素和移除集合
//单个移除 移除发现的第一个
c1.remove(188);
System.out.println(c1);
//集合移除 移除此集合中所有的元素 包含原集合中重复的元素
c1.removeAll(c2);
System.out.println(c1);
//清空全部元素 clear()
c1.clear();
System.out.println(c1);
//转换为数组 toArray()
System.out.println(c2.toArray());
Object[] object = c2.toArray();
System.out.println(object[1]);
//遍历 因为Collection本身是无序的 不能通过下标定(索引)定位元素 故遍历一般有三种方式
System.out.println("foreach-------------------------------------------------------");
//foreach
for(Object obj:c2) {
System.out.println(obj);
}
System.out.println("迭代器-----------------------------------------------------------");
//迭代器
//1.得到迭代器
Iterator i2 = c2.iterator();
//执行过程 1.判断游标后面是否存在元素 存在返回ture
while(i2.hasNext()) {
//执行过程 2.返回游标的下一个元素 并将游标后移
System.out.println(i2.next());
}
System.out.println("Lambda--------------------------------------------------");
//Lambda 表达式遍历集合
c2.forEach(obj -> System.out.println(obj));
}
}
List集合
List 是一个元素有顺序、元素可重复的集合,集合中的每个元素都有对应的索引。
List 可以针对索引来操作集合的元素,比如插入、替换和删除集合元素。
List本身也是一个接口不可被实例化 因此需要用到ArrayList类或Vector类来实现。
ArrayList和Vector实现类
特点
☼它们都是基于数组实现的 List 类,封装了一个动态的、允许再分配的 Object[] 数组,主要使用initialCapacity 参数来设置该数组的长度,当添加的元素数量过多的话,则 initialCapacity 会自动增长,默认长度是 10。
☼有时候需要注意性能问题,如果向这两个集合中添加大量元素时,可用 ensureCapacity(int minCapacity) 方法一次性地增加initialCapacity,这样可以减少重分配的次数,提高新能。
☼它们也可以使用 ensureCapacity(int minCapacity) 和 trimToSize() 方法来重新分配 Object[] 数组。
☼Vector 是一个比较老旧的集合,是 ArrayList 的前身,有很多缺点,不使用。
☼ArrayList 是线程不安全的,如果多个线程访问&修改了 ArrayList 集合,就需要手动保证集合的同步
性。
☼Vector 是线程安全的,所以性能会比 ArrayList 稍低,哪怕是线程安全也不推荐使用。后面,我们可以
用 Collections 工具类来讲 ArrayList 变成线程安全的。
☼ArrayList相对比于其父类接口中多出的显著特点就是有顺序 有无顺序主要体现在是否可以通过下标来操作数据
☼因此ArrayList中特有的方法主要也是根据有序这个特点来的
ArrayList总结
底层数组集合 遍历快、访问元素的速度也快、插入和删除速度慢 、不同步(线程不安全)
演示实例
import java.util.ArrayList;
import java.util.ListIterator;
public class ArrayListDemo {
public static void main(String[] args) {
ArrayList l1 = new ArrayList();
l1.add(1);
l1.add(2);
l1.add(3);
l1.add(4);
//通过下标获取数据get()
System.out.println(l1.get(1));
//替换 将指定位置的数据更改
l1.set(3, 5);
System.out.println(l1);
//返回元素第一次出现的下标值indexof()
System.out.println(l1.indexOf(5));
//通过下标删除数据 删除完成后返回的是该下标数据的值
//l1.remove(3);
System.out.println(l1.remove(3));
System.out.println(l1);
//注意此时仍然可以使用数据本身来删除 注意传入整数数据时要进行类型转换 删除完成后返回true
l1.remove((Integer)1);
System.out.println(l1);
l1.add(4);
l1.add(5);
l1.add(6);
//可以倒序输出了 for循环 和迭代器 演示
System.out.println("for--------------------------------------------------");
for(int i=l1.size();i>0;i--) {
System.out.println(l1.get(i-1));
}
System.out.println("迭代器--------------------------------------------");
//需要先正序才能倒序
System.out.println("正序-------------------------");
ListIterator listIterator = l1.listIterator();
while(listIterator.hasNext()) {
System.out.println(listIterator.next());
}
System.out.println("倒叙-------------------------");
while(listIterator.hasPrevious()) {
System.out.println(listIterator.previous());
}
}
}
泛型
是什么 简单讲在集合后面加入<数据类型> 便是泛型了
ArrayList<String> l1 = new ArrayList<String>();//使用泛型来限制集合可传入的数据类型
作用
用于限制集合,存储类型 用了泛型之后只能存储同种类型数据。
泛型除了可以在集合中使用之外 也可以在类和方法中使用
好处
安全性更高 消除了绝大部分类型转换问题 增加了维护性 可读性
使用示例
import java.util.ArrayList;
import java.util.ListIterator;
public class GenericDemo{
public static void main(String[] args) {
//使用泛型来限制集合可传入的数据类型
ArrayList<String> book = new ArrayList<String>();
book.add("Java程序设计");
book.add("C语言入门");
book.add("Python大法好");
book.add("Bug修改入门");
book.add("追求测试小姐姐话术");
//可以直接用于赋值运算 不需要考虑复杂的类型问题 简单易维护
String s = book.get(4)+book.get(3);
System.out.println(s);
//foreach可以使用特点类型了 不需要再使用Object了
for(String str : book) {
System.out.println(str);
}
ListIterator<String> listIterator = book.listIterator();
while (listIterator.hasNext()) {
System.out.println(listIterator.next());
}
}
}
长度不变的List
Arrays 类的 asList(Object… a) 方法,可以把一个数组或指定个数的对象转成一个 List 集合,这个集合
既不是 ArrayList 实现类的实例,也不是 Vector 实现类的实例,而是 Arrays 的内部类 ArrayList 的实
例。
Arrays.ArrayList 是一个固定长度的 List 集合,只能访问元素,不能添加和删除集合中的元素。
示例
import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;
public class ArraysDemo {
public static void main(String[] args) {
//asList(T... a)
//... 表示可以存放多个元素
//返回的这个集合 长度不可变 不能添加不能删除
List<String> bookList = Arrays.asList("基督山伯爵","追风筝的人","资治通鉴","五年高考三年模拟");
System.out.println(bookList);
//getClass()获取对象的实现类
System.out.println(bookList.getClass());
//ForEach() 遍历集合
bookList.forEach(System.out::println);
}
}