1、集合概述

  • 什么是集合?集合有什么用?

    • 数组其实就是一个集合,集合实际上是一个容器,它可以容纳其他类型的数据,集合为什么在开发中使用最多?
      • 集合是一个容器,是一个载体,可以容纳多个对象,在实际开发中,假设连接数据库,数据库种有10条记录,那么假设把10条记录查询出来,在java程序中会将10条数据封装成10个java对象,然后将10个对象放在一个集合中,将集合传到前端,然后遍历集合,将一个数据一个数据展现出来
    • 集合不能存储基本数据类型,也不能存储java对象,集合当中存储的都是java对象的内存地址,(或者说集合中存储的是引用),集合在java中本身是一个对象,集合中任何时候存储的都是引用
    • java中每一个不同的集合,底层会对应的不同的数据结构,往不同的集合中存储元素,等于将数据放到了不同的数据结构中去,什么是数据结构?数据存储的结构就是数据结构,不同的数据结构,数据存储方式不同,例如:
      • 数组
      • 链表
      • 哈希表
      • 使用不同的集合就是使用不同的数据结构

        2、集合在java jdk哪个包下?

  • java.util.*

    • 所有的集合类和集合接口都在java.util下

      3、背会集合的继承结构图

      4、集合分类

      4.1单个方式存储元素,这一类集合超级父接口:java.util.Collection

      image.png
      image.png

      4.2 键值对的方式,超级父接口,java.util.

      image.png

4.3 总结

  • ArrayList: 底层是数组
  • LinkedList: 底层双向列表
  • Vector: 底层是数组,线程安全的,效率低,使用较少
  • HashSet: 底层是HashMap,放到HashSet集合中的元素等同于放到HashMap集合key部分了
  • TreeSet: 底层是TreeMap,放到TreeSet集合中的元素等同于放到TreeMap集合key部分了
  • HashMap: 底层是哈希表
  • Hashtable:底层也是哈希表,只不过线程安全的,效率较低,使用较少
  • Properties: 线程安全,key和value只能存储字符串String
  • TreeMap: 底层是二叉树,TreeMap中的key可以按照自动大小排序

    4.4 特点

    image.png

    5、collection

    5.1 集合中通用方法

    ```python package com.collection;

import com.oop.Student;

import java.util.ArrayList; import java.util.Collection;

/ java.util.collection 中常用的方法 1、Collection 中能存放什么元素 没有使用泛型之前,Collection中可以存储object所有子类型 使用了泛型之后,Collection只能存储某个具体类型 Collection中什么都能存,只能是object的子类就行 集合中不能直接存储基本数据类型,不能存储java对象,只是存储java对象的内存地址 / public class Demo01 { public static void main(String[] args) { // 1、创建一个对象 // Collection collection = new Collection(); 接口是抽象的,无法实例化 Collection c = new ArrayList(); c.add(100);// 实际放进去一个对象的内存地址,Integer x = new Integer() c.add(new Student1());// 自动装箱

  1. //2、获取集合中元素个数
  2. System.out.println("集合中的元素个数:"+c.size());
  3. // 3、判断集合中是否包含元素
  4. System.out.println("集合中是否包含元素100:"+c.contains(100));
  5. // 4、移除元素
  6. c.remove(100);
  7. System.out.println("集合中是否包含元素100:"+c.contains(100));
  8. // 5、isEmpty()
  9. System.out.println("集合中元素是否为空:" + c.isEmpty());
  10. // 6、元素清空 clear
  11. // 7、将集合转为数组
  12. Object[] objs = c.toArray();
  13. for(int i = 0; i < objs.length; i++){
  14. Object o = objs[i];
  15. System.out.println(o);
  16. }
  17. }

}

class Student1{

}

  1. <a name="RN0gk"></a>
  2. #### 5.2 关于集合中遍历|迭代专题(重点 *****)
  3. ```python
  4. package com.collection;
  5. import java.util.Collection;
  6. import java.util.HashSet;
  7. import java.util.Iterator;
  8. /*
  9. 关于集合中遍历|迭代专题(重点 *****)
  10. */
  11. public class Demo02 {
  12. public static void main(String[] args) {
  13. // 以下讲解的是通用的迭代、遍历方式
  14. // Map中不能用,在所有的collection以及子类中使用
  15. //创建集合对象
  16. Collection c = new HashSet();
  17. c.add("abc");
  18. c.add(100);
  19. c.add(true);
  20. c.add(3.14);
  21. Iterator iterator = c.iterator();
  22. while(iterator.hasNext()){
  23. Object obj = iterator.next();
  24. System.out.println("迭代元素: " + obj);
  25. }
  26. // 迭代元素: abc
  27. // 迭代元素: 100
  28. // 迭代元素: 3.14
  29. // 迭代元素: true
  30. }
  31. }

5.3 Collection集合的contains方法

image.png

  1. package com.collection;
  2. import java.util.ArrayList;
  3. import java.util.Collection;
  4. /*
  5. Collection集合的 contains方法
  6. contains方法是判断集合中是否包含某个元素的方法
  7. 调用了equals方法进行比对
  8. equals方法返回true则包含
  9. */
  10. public class Demo03 {
  11. public static void main(String[] args) {
  12. Collection c = new ArrayList();
  13. String s1 = new String("abc");
  14. c.add(s1);
  15. String s2 = new String("def");
  16. c.add(s2);
  17. System.out.println(c.size());//2
  18. String x = new String("abc");
  19. System.out.println(c.contains(x));//true String类的equals方法重写了比较内容
  20. }
  21. }

5.5 存放在集合中的类型要重写equals方法

  1. package com.collection;
  2. import java.util.ArrayList;
  3. import java.util.Collection;
  4. public class Demo04 {
  5. public static void main(String[] args) {
  6. Collection c = new ArrayList();
  7. User u1 = new User("jack");
  8. User u2 = new User("jack");
  9. c.add(u1);
  10. System.out.println(c.contains(u2)); // 为重写equals方法 返回false
  11. }
  12. }
  13. class User{
  14. private String name;
  15. public User() {}
  16. public User(String name) {
  17. this.name = name;
  18. }
  19. @Override
  20. public boolean equals(Object obj) {
  21. if (obj == null || !(obj instanceof User)) return false;
  22. if (obj == this) return true;
  23. User u = (User)obj;
  24. return u.name.equals(this.name);
  25. }
  26. }

5.6 remove方法

  1. package com.collection;
  2. import java.util.ArrayList;
  3. import java.util.Collection;
  4. public class Demo05 {
  5. public static void main(String[] args) {
  6. Collection c = new ArrayList();
  7. String s1 = new String("abc");
  8. c.add(s1);
  9. String s2 = new String("abc");
  10. c.remove(s2);
  11. System.out.println(c.contains(s1));//false, remove重写了equals方法,删除了内容abc
  12. }
  13. }

5.7 集合结构发生改变,迭代器需要重新获取

  1. package com.collection;
  2. import java.util.ArrayList;
  3. import java.util.Collection;
  4. import java.util.Iterator;
  5. /*
  6. 集合结构发生改变时,迭代器必须重新获取,否则发生异常,Java.util.ConcurrentModifycationException
  7. 编写代码时,next()方法返回值类型必须时Object
  8. iterator.remove();// 0 迭代器删除的一定是当前元素
  9. */
  10. public class Demo06 {
  11. public static void main(String[] args) {
  12. Collection c = new ArrayList();
  13. c.add("abc");
  14. c.add("def");
  15. Iterator iterator = c.iterator();
  16. while (iterator.hasNext()){
  17. Object o = iterator.next();
  18. // c.remove(o);
  19. System.out.println(o);
  20. System.out.println(iterator.hasNext());
  21. iterator.remove();// 0 迭代器删除的一定是当前元素
  22. }
  23. System.out.println(c.size());
  24. }
  25. }

6、List特有方法

  1. package com.collection;
  2. import java.util.ArrayList;
  3. import java.util.Iterator;
  4. import java.util.List;
  5. /*
  6. 1List集合存储元素特点
  7. 有序:List集合中的元素有下标
  8. 0开始,以1递增
  9. 可重复,存储1一个1,还可存储1
  10. 2List既可以是Collection接口的子接口,那么List肯定有自己的特色方法
  11. 以下是List方法特有的方法
  12. void add(int index, E element) 将指定的元素插入此列表中的指定位置(可选操作)。
  13. E get(int index) 返回此列表中指定位置的元素。
  14. int indexOf(Object o) 返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1
  15. E remove(int index) 删除该列表中指定位置的元素(可选操作)。
  16. int lastIndexOf(Object o) 返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1
  17. E remove(int index) 删除该列表中指定位置的元素(可选操作)。
  18. E set(int index, E element) 用指定的元素(可选操作)替换此列表中指定位置的元素。
  19. */
  20. public class Demo07 {
  21. public static void main(String[] args) {
  22. List myList = new ArrayList();
  23. //添加元素,默认向元素末尾添加元素
  24. myList.add("abc");
  25. myList.add("def");
  26. myList.add(1,100);
  27. System.out.println(myList.lastIndexOf(100));
  28. // 通过下表获取元素
  29. Object obj1 = myList.get(1);
  30. System.out.println(obj1);
  31. Iterator c = myList.iterator();
  32. while(c.hasNext()){
  33. Object obj = c.next();
  34. System.out.println(obj);
  35. }
  36. }
  37. }

6.1 ArrayList

  • ArrayList集合初始化容量是10
  • 集合底层是object[] 数组
  • 使用的哪个集合最多? ```python package com.collection;

/ ArrayList 集合 1、默认初始化容量是10 2、集合底层是object数组 3、构造方法 new ArrayList() new ArrayList(20) 4、ArrayList集合内容 增长到原来的1.5倍 ArrayList集合底层是数组,怎么优化? 尽可能少的内容,因为数组扩容效率比较低,建议使用ArrayList集合 的时候预估元素的个数,给定一个初始化容量 5、数组优点 检索效率比较高,每个元素占用空间大小相同,内存地址连续,知道首元素内存地址,然后知道下标, 通过数据表达式就能计算元素的内存地址,所以检索效率高。 缺点 随机增删元素的效率比较低 6、向数组末尾添加元素 随机增删元素效率比较低 7、向数组末尾添加元素,效率很高,不受影响 8、面试官经常问的问题? 这么多的集合中,你用的哪个集合最多? ArrayList 因为往数组末尾添加元素,效率不受影响 另外,我们检索或查找某个元素的操作比较多 / public class Demo08 { public static void main(String[] args) { / ArrayList(Collection<? extends E> c) 构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序。 / Collection c = new ArrayList();

  1. c.add(100);
  2. c.add("abc");
  3. List c1 = new ArrayList(c);
  4. for(int i = 0; i < c1.size(); i ++){
  5. Object o = c1.get(i);
  6. System.out.println(o);
  7. }
  8. }

}

  1. <a name="ZsVF4"></a>
  2. ### 7、链表的数据结构
  3. <a name="UlQZW"></a>
  4. #### 7.1 概念
  5. - 基本单元-节点
  6. - 有两个属性,data(存储的数据),next(下一节点的内存地址)
  7. - 优点
  8. - 增删效率高,不涉及大量元素位移问题
  9. - 缺点
  10. - 查询效率低,每一次查询某个元素的时候需要从头节点开始往下遍历
  11. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12881754/1625403632521-0f6b68ac-27e8-4287-874e-812d677c954a.png#clientId=u8c153e9d-933d-4&from=paste&height=354&id=u399cd7e6&margin=%5Bobject%20Object%5D&name=image.png&originHeight=707&originWidth=1405&originalType=binary&ratio=1&size=467000&status=done&style=none&taskId=u677da7cb-6710-423e-8d7d-be334397e9b&width=702.5)
  12. <a name="K5Nhv"></a>
  13. #### 7.2 单链表实现
  14. ```python
  15. // client
  16. package com.danlink;
  17. public class Link {
  18. // 定义头节点
  19. Node header = null;
  20. int size = 0;
  21. /*
  22. 查找集合最后一个元素
  23. */
  24. public Node findLastNode(Node node){
  25. if (node.next == null){
  26. return node;
  27. }
  28. return findLastNode(node.next);
  29. }
  30. /*
  31. 查找某个元素
  32. */
  33. // 返回元素个数
  34. public int size(){
  35. return size;
  36. }
  37. // 添加链表中某个数据
  38. public void add(Object data){
  39. if (header == null){
  40. header = new Node(data,null);
  41. }else{
  42. Node lasNnode = findLastNode(header);
  43. lasNnode.next = new Node(data,null);
  44. }
  45. size += 1;
  46. }
  47. // 删除
  48. public void remove(Object obj){
  49. }
  50. // 修改
  51. public void modify(Object obj){
  52. }
  53. // 查询
  54. public void find(Object obj){
  55. }
  56. }
  57. // Node
  58. package com.danlink;
  59. /*
  60. 单链表中的节点
  61. 节点是单链表的基本单元
  62. 每一个节点Node都有两个属性
  63. 一个属性:是存储的数据
  64. 另一个属性:是下一个节点的内存地址
  65. */
  66. public class Node {
  67. // 存储的数据
  68. Object data;
  69. // 下一个节点的地址
  70. Node next;
  71. public Node() {}
  72. public Node(Object data, Node next) {
  73. this.data = data;
  74. this.next = next;
  75. }
  76. }
  77. // link
  78. package com.danlink;
  79. public class Link {
  80. // 定义头节点
  81. Node header = null;
  82. int size = 0;
  83. /*
  84. 查找集合最后一个元素
  85. */
  86. public Node findLastNode(Node node){
  87. if (node.next == null){
  88. return node;
  89. }
  90. return findLastNode(node.next);
  91. }
  92. /*
  93. 查找某个元素
  94. */
  95. // 返回元素个数
  96. public int size(){
  97. return size;
  98. }
  99. // 添加链表中某个数据
  100. public void add(Object data){
  101. if (header == null){
  102. header = new Node(data,null);
  103. }else{
  104. Node lasNnode = findLastNode(header);
  105. lasNnode.next = new Node(data,null);
  106. }
  107. size += 1;
  108. }
  109. // 删除
  110. public void remove(Object obj){
  111. }
  112. // 修改
  113. public void modify(Object obj){
  114. }
  115. // 查询
  116. public void find(Object obj){
  117. }
  118. }

7.3 链表的优点和缺点

  • 链表的优点
    • 链表的元素在空间存储上内存地址不连续
    • 随机增删元素的时候不会有大量元素位移,因此随机增删效率高,建议在随机增删的业务场景较多时使用LinkedList
  • 链表的缺点
    • 不能通过数学表达式计算查找元素的内存地址,每一次查找都是从头节点开始遍历,直到找到为止,所以linkedList集合索引/查找的效率较低
  • ArrayList:把检索发挥到极致,末尾添加元素效率很高,索引效率高不是因为下标的原因,是因为底层数组发挥的作用,linkedList同样有下标,只能从头节点一个一个遍历
  • LinkedList:把随机增删发挥到极致,
  • 加元素都是到末尾添加,

    7.4 末尾添加元素效率为什么高?

    image.png

  • 找位置通过可计算的内存地址找到,不需要从头开始一个一个遍历

    7.5 LinkedList 源码分析(双向链表)

    image.png

7.6 分析

  1. package kyrie.bao.com.collection;
  2. import java.util.LinkedList;
  3. import java.util.List;
  4. public class Demo01 {
  5. public static void main(String[] args) {
  6. List list = new LinkedList();
  7. list.add("a");
  8. list.add("b");
  9. list.add("c");
  10. for (int i = 0; i < list.size(); i++) {
  11. Object obj = list.get(i);
  12. System.out.println(obj);
  13. }
  14. }
  15. }

image.png

7.7 Vextor

  1. 非线程安全变成线程安全的
  2. List mylist = new ArrayList();
  3. Collection.syschronizedList(mylist);
  4. mylist.add("a");
  5. mylist.add("b")