一、概述
(一)什么是集合
Java 集合框架 Java Collection Framework ,又被称为容器 container ,是定义在 java.util 包下的一组接口 interfaces和其实现类 classes。
接口和类总览
(二)容器背后对应的数据结构
1. Collection:是一个接口,包含了大部分容器常用的一些方法
2. List:是一个接口,规范了ArrayList 和 LinkedList中要实现的方法
ArrayList:实现了List接口,底层为动态类型顺序表
LinkedList:实现了List接口,底层为双向链表
3. Stack:底层是栈,栈是一种特殊的顺序表
4. Queue:底层是队列,队列是一种特殊的顺序表
5. Deque:是一个接口
6. Set:集合,是一个接口,里面放置的是K模型
HashSet:底层为哈希桶,查询的时间复杂度为O(1)
TreeSet:底层为红黑树,查询的时间复杂度为O( ),关于key有序的
7. Map:映射,里面存储的是K-V模型的键值对
HashMap:底层为哈希桶,查询时间复杂度为O(1)
TreeMap:底层为红黑树,查询的时间复杂度为O( ),关于key有序
(三) 数组和集合的对比
1、数组和集合的元素存储的个数问题。
数组定义后类型确定,长度固定
集合类型可以不固定,大小是可变的。
2、数组和集合存储元素的类型问题。
数组可以存储基本类型和引用类型的数据。
集合只能存储引用数据类型的数据,不支持基本类型(如果非要用基本类型可以用包装类)。
3、数组和集合适合的场景
数组适合做数据个数和类型确定的场景。
合适合做数据个数不确定,且要做增删元素的场景。
3、数组和集合的存储内容
数组和集合中存储的都是元素对象的地址。
二、Collection集合体系
(一)集合总览
Collection集合特点
List系列集合 :添加的元素是有序、可重复、有索引。
ArrayList、LinekdList :有序、可重复、有索引。
Set系列集合 :添加的元素是无序、不重复、无索引。
HashSet: 无序、不重复、无索引;
LinkedHashSet: 有序 、不重复、无索引。
TreeSet: 按照大小默认升序排序、 不重复、无索引
Collection API通用:
(注意:Collection是单列集合的祖宗接口,它的功能是全部单列集合都可以继承使用的。)
方法名称 | 说明 |
public boolean add(E e) | 把给定的对象添加到当前集合中 |
public void clear() | 清空集合中所有的元素 |
public boolean remove(E e) | 把给定的对象在当前集合中删除 |
public boolean contains(Object obj) | 判断当前集合中是否包含给定的对象 |
public boolean isEmpty() | 判断当前集合是否为空 |
public int size() | 返回集合中元素的个数。 |
public Object[] toArray() | 把集合中的元素,存储到数组中 |
代码演示:
public class api2 {
public static void main(String[] args) {
// HashSet:添加的元素是无序,不重复,无索引。
Collection<String> c = new ArrayList<>();
// 1.add()添加元素, 添加成功返回true。
c.add("Java");
c.add("HTML");
System.out.println(c.add("HTML"));
c.add("MySQL");
c.add("Java");
System.out.println(c.add("bite"));
System.out.println(c); // 结果:[Java, HTML, HTML, MySQL, Java, bite]
// 2.清空集合的元素。
// c.clear();
// System.out.println(c);
// 3.判断集合是否为空 是空返回true,反之。
// System.out.println(c.isEmpty());
// 4.获取集合的大小。
System.out.println(c.size());
// 5.判断集合中是否包含某个元素。
System.out.println("判断集合中是否包含某个元素测试");
System.out.println(c.contains("Java")); // true
System.out.println(c.contains("java")); // false
System.out.println(c.contains("bite")); // true
// 6.删除某个元素:如果有多个重复元素默认删除前面的第一个!
System.out.println("删除测试");
System.out.println(c.remove("java")); // false
System.out.println(c);
System.out.println(c.remove("Java")); // true
System.out.println(c);
// 7.把集合转换成数组 [HTML, HTML, MySQL, Java, bite]
System.out.println("集合转换测试");
Object[] arrs = c.toArray(); // 这里用object是因为在实际业务中不确定集合的数据类型是啥
System.out.println("数组:" + Arrays.toString(arrs));
//复制数组
System.out.println("复制测试");
Collection<String> c1 = new ArrayList<>();
c1.add("java1");
c1.add("java2");
System.out.println(c1); //[java1, java2]
Collection<String> c2 = new ArrayList<>();
c2.add("小黑");
c2.add("小白");
System.out.println(c2); //[小黑, 小白]
// addAll把c2集合的元素全部放入到c1中去。
c1.addAll(c2);
System.out.println(c1);
System.out.println(c2);
}
}
Collection集合的遍历方式
方式一:迭代器
迭代器在 Java 中的代表是 Iterator ,迭代器是集合的专用遍历方式。
Iterator<E> iterator() :返回集合中的迭代器对象,该迭代器对象默认指向当前集合的0索引。
注意:越界会出现NoSuchElementException异常。
public class CollectionDemo01 {
public static void main(String[] args) {
ArrayList<String> lists = new ArrayList<>();
lists.add("赵敏");
lists.add("小昭");
lists.add("素素");
lists.add("灭绝");
System.out.println(lists);
// [赵敏, 小昭, 素素, 灭绝]
Iterator<String> it = lists.iterator();
// 1、得到当前集合的迭代器对象。
// String ele = it.next();
// System.out.println(ele);
// System.out.println(it.next());
// System.out.println(it.next());
// System.out.println(it.next());
// System.out.println(it.next()); // NoSuchElementException 出现无此元素异常的错误
// 2、定义while循环(推荐使用)
while (it.hasNext()) { // 判断是否有下一个元素
String ele = it.next(); //取出下一个元素
System.out.println(ele);
}
}
}
方式二:foreach/增强for循环
增强for循环:既可以遍历集合也可以遍历数组。
格式:
for(元素数据类型 变量名 : 数组或者Collection集合) {
//在此处使用变量即可,该变量就是元素
}
//遍历数组[赵敏, 小昭, 素素, 灭绝]
for (String ele : lists) {
System.out.println(ele);
}
System.out.println("------------------");
double[] scores = {100, 99.5, 59.5};
for (double score : scores) {
System.out.println(score);
if(score == 59.5){
score = 100.0; // 因为已经取出来了,修改的是取出来的值,
// 所以修改无意义,不会影响数组的元素值。
}
}
System.out.println(Arrays.toString(scores));
}
方式三:lambda表达式
方法名称
说明
default void forEach(Consumer<? super T> action):
结合lambda遍历集合
// 遍历[赵敏, 小昭, 殷素素, 周芷若]
// Lambda表达式
lists.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
System.out.println("-------------");
// 使用匿名内部类的简化写法
// lists.forEach(s -> {
// System.out.println(s);
// });
//更简化的写法
lists.forEach(s -> System.out.println(s) );
//还可以这样写 lists.forEach(System.out::println );
三、List系列
1.List系列集合特点
ArrayList、LinekdList :有序,可重复,有索引。
- 有序:存储和取出的元素顺序一致
- 有索引:可以通过索引操作元素
- 可重复:存储的元素可以重复
List集合特有方法
List集合因为支持索引,所以多了很多索引操作的独特api,其他Collection的功能List也都继承了。
方法名称
说明
void add(int index,E element)
在此集合中的指定位置插入指定的元素
E remove(int index)
删除指定索引处的元素,返回被删除的元素
E set(int index,E element)
修改指定索引处的元素,返回被修改的元素
E get(int index)
返回指定索引处的元素
List集合的遍历方式
迭代器
增强 for 循环
Lambda 表达式
f or 循环(因为 List 集合存在索引,和数组的for循环遍历方式一样。)
3、List系列的底层原理
ArrayList集合底层原理
ArrayList底层是基于数组实现的:根据索引定位元素快,增删需要做元素的移位操作。
第一次创建集合并添加第一个元素的时候,在底层创建一个默认长度为10的数组。
LinkedList的底层原理
底层数据结构是双链表,查询慢,首尾操作的速度是极快的,所以多了很多首尾操作的特有API。
ArrayList和LinkedList详细讲解请看下文
四、Set,Map的讲解
请看下文