一、概述
(一)什么是集合
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 :有序,可重复,有索引。
- 有序:存储和取出的元素顺序一致
- 有索引:可以通过索引操作元素
- 可重复:存储的元素可以重复
2、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的讲解
请看下文