A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

© 卞建彬 中级黑马   /  2018-9-20 15:24  /  857 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

杜铁岭:


一 i笔记 1. 数据存储的常用结构有:栈,队列,数组,链表和红黑树 2. 栈:先进后出 (入口和出口在同一侧) 3. 队列:先进先出 (入口和出口在集合的两侧) 4. 数组:查询快(数组的地址是连续的,我们通过数组的首地址可以找到数组,通过数组的索引 可以快速查找某一个元素),增删慢(数组的长度是固定的,我们想要增加/删除一个元素,必须 创建一个新数组,把原数组的数据复制过来 5. 链表:查询慢(链表中的地址不是连续的,每次查询元素,都必须从头开始查询),增删快(链表 结构,增加/删除一个元素,对链表的整体结构没有影响,所以增删快). 6. 链表中的每一个元素也称之为一个节点 一个节点包含了一个数据源(存储数组),两个指针域(存储地址) 自己的地址/数据/下一个节点的地址 7. 链表分为两种 单向链表:链表中只有一条链子,(连接所有元素),不能保证元素的顺序(存储 元素和取出元素的顺序有可能不一致)  双向链表:链表中有两条链子,有一条链子是专门记录元素的顺序,是一个有序的集合 8. 二叉树:分支不能超过两个 左边可以叫:左孩子 左子树 9. 排序树/查找树 在二叉树的基础上,元素是有大小顺序的 左子树小,右子树大 10. 平衡树:左孩子的数量和右孩子相等 11. 不平衡树:左孩子!=右孩子 12. 红黑树: 特点: 趋近于平衡树,查询的速度非常的快,查询叶子节点大次数和小次数不能超过2倍 约束: 1. 节点可以是红色的或者黑色的 2. 根节点是黑色的 3. 叶子节点(空节点)是黑色的 4. 每个红色的节点 的子节点都是黑色的 5. 任何一个节点到其每一个叶子节点的所有路径上黑色节点数相同 13.java.util.List 接口 extends Collection接口 List接口的特点: 1. 有序的集合,存储元素和取出元素的顺序是一致的. 2. 有索引,包含了一些带索引的方法 3. 允许存储重复的元素 List接口中带有索引的方法(特有)
注意: 操作索引的时候,一定要防止索引越界异常 三种异常: IndexOutOfBoundsException索引越界异常 ArrayIndexOutofBoundsException数组索引越界异常 StringIndexOutofBoundsException 字符串索引越界异常 14.ArrayList集合 此实现不是同步的,多线程意 味着效率高速度快(底层是一个数组结构,查 询快增删慢) 15.LinkedList List接口的链表实现(查询慢,增删快),注意,此实现不是同步的,多线程-->速 度快,有大量操作首尾元素的方法 特点: 1. 底层是一个链表结构:查询慢,增删快 2. 里边包含了大量操作首尾元素的方法 注意:使用LinkedList集合特有的方法,不能使用多态 添加: 创建 LInkedList 集合对象 等效push/addFirst (E e):将指定元素插入此列表的开头 等效addList /add 获取: getFirst 获取并返回第一个元素 getLast 在清空以后再获取会抛出 NoSuchElementException获取元素异常 移除并返回: removeFirst/pop removeLast 16. Vector集合底层是一个数组 单线程 1.2版本实现了List接口 17. Set extends Collection接口 特点:1.不允许存储重复的元素  2.没有索引,没有带索引的方法,也不能使用普通的for循环遍历 18. HashSet 哈希表结构 无序结构 此实现也不是同步的(多线程) 特点:是一个无序的集合,存储元素和去取出元素的顺序有可能不一致 底层是一个哈希表结构(查询的速度非常快 ) 19. HashSet集合存储数据的结构(哈希表) 20. 哈希值:是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,是模 拟出来的得到的地址,不是数据实际存储的物理地址). 在Object类有一个方法,可以获取对象的哈希值.
int hashCode() 返回该对象的哈希码值. public native int hashCode(); native :代表方法调用的是本地操作系统的方法. 21.String类的哈希值 String 类重写Object类的hashCode方法 22.jdk 1.8版本之前:哈希表= 数组+链表    Jdk1.8版本之后:哈希表 = 数组+链表                  哈希表 = 数组+红黑树(提高查询的速度) 哈希表的特点:速度快 数据结构:把元素进行了分组.(相同哈希值的元素是一组)链表/红黑树结构把相同哈希值的元 素连接到一起 两个元素不同,但是哈希值相同 哈希冲突 如果链表的元素超过了8位 那么就会把链表转化为红黑树(提高查询速度) 23. Set集合在调用add方法的时候,add方法会调用元素的hashCode方法和equals方法,判 断元素是否重复 24. LinkedHashSet集合的特点: 底层是一个哈希表(数组+链表/红黑树) + 链表:多了一条链表(记录元素的存储顺序),保证元 素有序 25.  可变参数:是jdk1.5之后出现的新特性 26. 使用前提:  当方法的参数列表数据类型已经确定,但是参数的个数不确定,就可以使用使用可变参数 使用格式:  修饰符 返回值类型 方法名(数据类型... 变量名){} 可变参数的原理: 可变参数底层就是一个数组,根据传递参数个数不同,会创建不同长度的数组,来存储这些 参数. 传递参数个数,可以是0个(不传递),1,2...多个 [ 中括号代表一个数组 可变参数的注意事项 1. 一个方法的参数列表,只能有一个可变参数 2. 如果方法的参数有多个,那么可变参数必须卸载参数列表的末尾 可变参数的终极写法 参数列表(Object...obj) 27. Collections sort方法参数默认是 List    28. 注意:sort 使用前提
被排序的集合里边存储的元素如果是自己定义的类),必须实现Comparable,重写接口中的方 法compareTo定义排序的规则 Comparable接口的排序规则 自己(this)- 参数:升序 Comparable:自己(this)和别人(参数)比较,自己需要事先Comparable接口,重写比较的规 则compareTo方法 Comparator:相当于找一个第三方的裁判,比较两个 前减后 升序排序  后减前 降序排序 二 课堂笔记 数据结构:就是数据的存储方式 栈特点:先进后出(FILO First In Last Out) 栈顶  入口    出口 模拟 栈底 存储元素到集合 入栈\压栈 取出集合中元素  出栈\弹栈 队列:先进先出 可用于处理高并发 数组: 查询快:数组的地址是连续,我们通过数组的首地址,可以找到数组,通过数组的索引可以 快速查找某一个元素 增删快:数组的长度是固定的,我们想要增加/删除一个数组,必须创建一个新数组,把原数 组的数据复制复制过来 链表: 查询慢:链表中地址不是连续的,每次查询元素,都必须从头开始查询 增删快:链表结构增加/删除一个元素,对链表的整体结构没有影响,所以增删快 链表中的每一个元素也称之为一个节点 一个节点包含了一个数据源(存储数据),两个指针域(存储地址) 单向链表:链表中只有一条链子,不能保证元素的顺序(存储元素和取出元素的顺序有可能不一 致) 双向链表:链表中有两条链子,有一条链子是专门记录元素的顺序,是一个有序的集合 链表查询 查询只能一个地址值接着一个地址值查询 节点 : 内存中不连续 (Node/Entry ) 单向链表: 只知道下一个节点地址值 双向链表:知道上一个和下一个节点的地址值 红黑树:是一种 平衡 二叉 查找 树
二叉树:分支不能超过两个 树根 左孩子/左子树 右孩子/右子树 树叶 排序树/查找树(查询速度快): 在二叉树的基础上,元素是有大小顺序的 左子树小,右子树大 平衡树:左孩子和右孩子数量相等 不平衡树:左孩子和右孩子数量不相等 红黑树: 特点:趋近于平衡树,查询的速度非常快,查询叶子节点大次数和小次数不能超过二倍 约束条件: 1. 节点可以是红色的或者黑色的 2. 根节点是黑色的 3. 叶子节点(空节点)黑色的 4. 每个共色的节点的子节点都是黑色的 5. 任何一个节点到其每一个叶子节点的所有路径上黑色节点数相同 添加元素: 先和节点值进行比较 如果新添加的元素之比当前节点元素值小,则放在当前节点的左边 叶子节点 (头上) 到根节点 数相同 2-节点:节点多只有2个子节点 3-节点:节点多只有3个子节点 (节点可以存两个数) 可以有两个分支 被提升上来的节点是红色的(线也是红色的) 树的遍历: 从根节点向左走一直到走不动 返回当前节点的值 往右走 返回上一层节点   迭代; 查询 增删 需要自动排序 比链表 效率高 List集合 (重写了toString方法) Java.util.List接口extends Collection接口 特点:
1. 有序的集合,存储元素和取出元素的顺序是一致的.  (存取顺序) 2. 有索引,包含了一些索引的方法 3. 允许存储重复的元素 注意: 操作索引的时候,一定要防止索引越界异常 Add 若原有索引上有元素,后面元素向后移 (数组结构)ArrayList(属于List子体系)集合 java.util.ArrayList 底层是一个数组 查询快,增删满 多线程 效率高速度快 特点: 线程不安全,效率高 API java.util.List<E>接口: // 常用特有成员方法 (都是按照索引来操作的) public?void?add(int?index,?E?element): 将指定的元素, 添加到该集合中的指定位置上 public?E?get(int?index): 返回集合中指定位置的元素 public?E?remove(int?index): 移除列表中指定位置的元素, 返回的是被移除的元素 public?E?set(int?index,?E?element): 用指定元素替换集合中指定位置的元素, 返回值的更新前的元素   java.util.LinkedList<E>类: 链表结构, 查询慢, 增删快 // 特有成员方法(主要操作开头和末尾元素) void?addFirst(E?e): 将指定元素插入此列表的开头 void?addLast(E?e): 将指定元素添加到此列表的结尾 E?getFirst(): 返回此列表的第一个元素 E?getLast(): 返回此列表的后一个元素 E?removeFirst(): 移除并返回此列表的第一个元素 E?removeLast(): 移除并返回此列表的后一个元素 E?pop(): (其实就是removeFirst())从此列表所表示的堆栈处弹出一个元素 栈stack void?push(E?e): (其实就是addFirst())将元素推入此列表所表示的堆栈 java.util.Collections类: 操作集合的工具类 // 静态方法 static?<T>?boolean?addAll(Collection<T>?c,?T...?elements):往集合中添加一些元素 static?void?shuffle(List<?>?list) :打乱集合顺序 static?<T>?void?sort(List<T>?list) :将集合中元素按照默认规则排序 static?<T>?void?sort(List<T>?list,Comparator<??super?T>?c):将集合中元素按照指定规则排序 LinkedList 多线程 底层是一个链表结构,查询慢,增删快 里边包含了大量操作守卫元素的方法 注意:不要用多态操作特有方法 pop--> 弹出 removefirst         push 压 -->addfirst 线程不安全效率高 Vector 同步的 -->单线程
Set接口 继承了Collections java.util.Set 特点: 1.不允许存储重复的元素 2.没有索引,没有带索引的方法,不能使用普通的for循环遍历 HashSet特点: 无序集合,存储元素和取出元素的顺序有可能不一致 底层是一个哈希表结构(查询的速度非常的快) 哈希表 = 数组 + 链表 或 红黑树 哈希算法:把任意的东西通过某种计算方式,转换为整数,通过数字代表这个事物 哈希值:是一个十进制的整数,由系统随机给出,是一个逻辑地址,是模拟出来得到的地址,不是 实际存储的的物理地址. native :代表该方法调用的是本地操作系统的方法 String类重写Objec类的hashCode方法  不同内容算出(两个元素不同)哈希值一样 ---> 哈 希冲突 哈希表特点:速度快 Jdk 1.8之前 哈希表 = 数组 + 链表 1.8后 = 数组 + 红黑树(提高查询速度) 如果挂的(链表长度超过了8位)元素超过8位,把链表转化成红黑树--->提高查询速度 数组的元素是一个链表 集合重写了toString 哈希表初始容量 16个 去重 应用Set 生成 equals 和 hashcode Hashset 存取顺序不一致 Linkedhashset 存取顺序一致 多一条链表 记录元素的存储顺序 可变参数:jdk1.5之后出现的新特性 使用前提:当方法的参数列表数据类型已经确定,但是参数的个数不确定,就可以使用可变 参数. 使用格式:定义方法时使用 修饰符 返回值类型 方法名(数据类型...变量名){} 可变参数的原理: 可变参数底层就是一个数组,根据传递参数个数不同,会创建不同长度的数组,来存储这些 参数. 传递的参数个数就,可以是0个(不传递)1,2,...多个 注意事项: 1. 一个方法的参数列表,只能有一个可变参数
2. 如果方法的参数有多个,那么可变参数必须写在参数列表的末尾. 可变参数的特殊写法:(终极) 参数列表(Object obj) Collections addAll(集合名,1,2,3) Set集合 (哈希值计算出来固定就放在那) 不可排序 List集合可排序 注意: Sort使用前提 自定义对象想要排序,必须实现Comparable,重写接口中的Comparato方法 返回0 认为元素都是相同的 自定义比较的规则,比较两个人的年龄(this,参数) Return this.getAge() - o.getAge() 升序 Comparable规则: 自己(this)-参数:升序 单项链表:方向,遍历的方向,只能从前往后遍历链表 2个成员变量 一个存数据,一个存下一个 节点的地址值 后一个存null 整个链表的地址值是第一个节点的地址值 双向链表:既能从前往后,也能从后往前遍历 存上下节点的地址值 数据  还有本身地址值 三.老师笔记 day03 List Set 今日内容 数据结构 集合     List集合     Set集合 Collections集合工具类 数据结构 数据结构: 就是数据的存储方式     不同的数据结构代表了不同的存储方式     不同的数据结构中, 会有不同的存入, 取出, 查找的方式和效率, 数据的存放方式也不同          如薯片, 可以用长纸筒装, 也可以用塑料包装袋装, 在两种容器中的存储方式就不同, 放入和取出的方式也 不一样
栈 知识点:
栈结构存入和取出数据的顺序有什么特点 栈结构适用于什么场景 总结: 栈:     ^  |     |  v |             |  出入口在同一端 | +---------+ | | |    3    | | | +---------+ | | +---------+ | | |    2    | |   栈 | +---------+ | | +---------+ | | |    1    | | | +---------+ | +-------------+
栈的特点:      先进后出 (FILO, First In Last Out)     入口和出口在同一侧      入栈(压栈): 将元素存入栈 出栈(弹栈): 从栈中取出元素
栈的适用场景:
    栈内存 (main方法先进栈调用, main方法中的其他方法都调用完毕后, main才能出栈)     反转内容 (车尾变车头, 进去再出来就反转了) 补充:
队列 知识点:
队列结构存入和取出数据的顺序有什么特点 队列结构适用于什么场景 总结:
队列:
入口                                                  出口       ----------------------------------------------                 +---------+ +---------+ +---------+    ---->            |    3    | |    2    | |    1    |  ---->                  +---------+ +---------+ +---------+       ----------------------------------------------
队列的特点:     先进先出 (FIFO, First In First Out)     入口和出口在两端      队列的适用场景:     秒杀, 抢购     在线售票     处理高并发场景
补充:
数组 知识点:
数组结构增删和查询数据有什么特点 数组结构适用于什么场景 总结:
数组:       0x01  0x02  0x03  0x04  0x05     +-----+-----+-----+-----+-----+     | "a" | "b" | "c" | "d" | "e" |     +-----+-----+-----+-----+-----+         0     1     2     3     4          数组的特点:     查询快: 通过 (第一个元素地址值 + 索引) 可以快速计算出该索引元素的地址值     增删慢: 增加一个元素, 要创建长度+1的新数组, 然后将原数组元素复制到新数组, 然后存入新元素; 删除 类似          // 添加元素     +-----+-----+-----+-----+-----+     | "a" | "b" | "c" | "d" | "e" |   如果要添加元素"f"
    +-----+-----+-----+-----+-----+              +-----+-----+-----+-----+-----+-----+     | "a" | "b" | "c" | "d" | "e" | "f" |  创建一个新数组, 将原数组元素复制进去, 然后存入新元素     +-----+-----+-----+-----+-----+-----+      数组的适用场景:     查询多, 增删少的数据存储场景   国内城市
补充:
链表 知识点:
链表结构增删和查询数据有什么特点 链表由什么组成 什么是单向链表 什么是双向链表 链表结构适用于什么场景 总结:
链表: 链表由多个 节点(Node / Entry) 组成     +-----+-----+-----+    +-----+-----+     |     |     |     |    |数据  |     |     +-----+-----+-----+    +-----+-----+
     单向链表: 每个节点存储 数据 和 下一个节点的地址值
链表 = 0x11
    0x11              0x44              0x88     +-----+-----+     +-----+-----+     +-----+-----+     | "a" | 0x44| --> | "b" | 0x88| --> | "c" | null|     +-----+-----+     +-----+-----+     +-----+-----+       数据  下一个      数据  下一个      数据  下一个
双向链表: 每个节点存储 数据, 上一个节点地址值 和 下一个节点地址值      0x11                    0x44                      0x88     +-----+-----+-----+      +-----+-----+-----+      +-----+-----+-----+     |null | "a" | 0x44| <--> |0x11 | "b" | 0x88| <--> |0x44 | "c" | null|     +-----+-----+-----+      +-----+-----+-----+      +-----+-----+-----+      上一个  数据  下一个     上一个  数据  下一个     上一个  数据  下一个
链表的特点:     查询慢: 要找到其中某个节点, 只能从第一个节点一个一个向后寻找     增删快: 只需要修改保存的下一个节点的地址值, 就可以快速完成增删          // 删除结点     +---+    +---+    +---+     | 1 |----| 2 |----| 3 |     +---+    +---+    +---+
    +---+             +---+     | 1 |-------------| 3 |     +---+             +---+              +---+              | 2 |              +---+      链表的适用场景:     查询少, 增删多的场景     链表可以实现栈和队列的结构, 因为栈和队列增删频繁 补充:
代码中链表节点的实现:
// 单向链表的节点 class Node<T> {     T data;       // 存储的数据     Node next;    // 下一个节点的地址值 }
// 双向链表的节点 class Node<T> {     T data;       // 存储的数据     Node before;  // 上一个节点的地址值     Node after;   // 下一个节点的地址值 } 红黑树 知识点:
红黑树结构有什么特点 红黑树结构适用于什么场景 总结:
红黑树: 是一种 平衡 二叉 查找 树     平衡: 左子节点和右子节点数量相等     二叉: 每个节点多有2个子节点     查找: 节点存储的元素是按照大小顺序存储的     特点:         元素存储过程中就完成了大小排序         查询比链表快, 增删比数组快 (数组和链表的折中)
红黑树的适用场景:     查询和增删都有, 需要元素自动排序的场景

树的遍历:
补充:
代码中树节点的实现
// 树的节点 class Entry<T> {     T data;           // 存储的数据     Entry left;       // 左子节点的地址值     Entry right;      // 右子节点的地址值     Entry parent;     // 父节点的地址值 } List集合 List介绍和常用方法 知识点:
List集合体系有什么特点 List接口中特有的按照索引操作的方法有哪些
总结:
List集合体系的特点:      1. 元素存取有序 (存入和取出元素的顺序一致)  3 2 1       3 2 1        2. 元素可以重复   3 2 2 1     3. 有索引 List子体系中的实现类都具有上述特点
java.util.List接口:     // 常用特有成员方法 (都是按照索引来操作的)      void add(int index, E element): 将指定的元素, 添加到该集合中的指定位置上     E get(int index): 返回集合中指定位置的元素     E remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素     E set(int index, E element): 用指定元素替换集合中指定位置的元素, 返回值的更新前的元素 补充:
ArrayList集合的特点 知识点:
ArrayList底层使用的是什么数据结构, 有什么特点 ArrayList适用于什么场景 总结:
ArrayList底层的数据结构:
    数组      ArrayList的特点:     查询快     增删慢     线程不安全, 效率高      ArrayList适用场景:     存储的数据"查询多, 增删少"的场景. 如用一个ArrayList存储中国城市名称 补充:
LinkedList集合的特点和特有方法 知识点:
LinkedList底层使用的是什么数据结构, 有什么特点 LinkedList适用于什么场景 LinkedList有哪些特有方法 总结:
LinkedList底层的数据结构:      链表      LinkedList的特点:     查询慢     增删快     线程不安全, 效率高      LinkedList适用场景:     存储的数据"查询少, 增删多"的场景. 如用LinkedList实现栈或队列      java.util.LinkedList<E>类: 链表结构, 查询慢, 增删快     // 特有成员方法(主要操作开头和末尾元素)     void addFirst(E e): 将指定元素插入此列表的开头     void addLast(E e): 将指定元素添加到此列表的结尾     E getFirst(): 返回此列表的第一个元素     E getLast(): 返回此列表的后一个元素     E removeFirst(): 移除并返回此列表的第一个元素     E removeLast(): 移除并返回此列表的后一个元素
    E pop(): (其实就是removeFirst())从此列表所表示的栈中弹出一个元素     void push(E e): (其实就是addFirst())将元素添加到此列表所表示的栈中 补充:
5分钟练习: 测试LinkedList特有方法
需求: 创建LinkedList集合, 添加元素1,2,3, 测试特有方法:     void addFirst(E e): 将指定元素插入此列表的开头     void addLast(E e): 将指定元素添加到此列表的结尾     E getFirst(): 返回此列表的第一个元素     E getLast(): 返回此列表的后一个元素     E removeFirst(): 移除并返回此列表的第一个元素     E removeLast(): 移除并返回此列表的后一个元素     E pop(): (其实就是removeFirst())从此列表所表示的栈中弹出一个元素     void push(E e): (其实就是addFirst())将元素添加到此列表所表示的栈中 代码:
public class Test {     public static void main(String[] args) {         // 创建LinkedList集合         LinkedList<Integer> list = new LinkedList<>();
        list.add(1);         list.add(2);         list.add(3);         System.out.println("初的集合:"+list);
        // void addFirst(E e): 将指定元素插入此列表的开头         list.addFirst(0);         System.out.println(list);
        // void addLast(E e): 将指定元素添加到此列表的结尾         list.addLast(9);         System.out.println(list);
        // E getFirst(): 返回此列表的第一个元素         Integer getFirst = list.getFirst();
        System.out.println("getFirst:" + getFirst);
        // E getLast(): 返回此列表的后一个元素         Integer getLast = list.getLast();         System.out.println("getLast:" + getLast);
        // E removeFirst(): 移除并返回此列表的第一个元素         Integer removeFirst = list.removeFirst();         System.out.println("removeFirst:" + removeFirst);
        // E removeLast(): 移除并返回此列表的后一个元素         Integer removeLast = list.removeLast();         System.out.println("removeLast:" + removeLast);
        // E pop(): (其实就是removeFirst())从此列表所表示的栈中弹出一个元素         Integer pop = list.pop();         System.out.println("pop:" + pop);
        // void push(E e): (其实就是addFirst())将元素添加到此列表所表示的栈中         list.push(666);         System.out.println(list);     } } Vector集合 知识点:
Vector底层使用的是什么数据结构, 有什么特点 总结:
JDK 1.0 版本中只有一个 Vector集合 JDK 1.2 开始增加了Collection集合体系
Vector底层的数据结构:      数组      Vector的特点:     查询慢     增删快     (同步)线程安全, 效率低
     Vector目前几乎没人使用 补充:
Set集合体系 HashSet集合 知识点: Set集合体系有什么特点  HashSet有什么特点, 底层采用什么数据结构  HashSet中的add()方法有什么特殊之处
总结:
Set集合体系特点:     1. 元素不可重复     2. 没有索引      HashSet特点:     1. 元素不可重复     2. 没有索引     3. 元素存取无序 (存入和取出顺序有可能不一致)     4. 底层采用 哈希表 结构. (查询快)         哈希表 = 数组 + 链表或红黑树
java.util.HashSet类:     // 常用方法     boolean add(E e): 添加元素, 根据元素的 hashCode() 和 equals() 方法判断是否重复. 重复则不添加并 返回false, 不重复则添加并返回true 补充:
5分钟练习: 使用HashSet添加元素 需求:  创建HashSet对象, 存储 5,5,4,4,3,3,2,2,1,1, 使用增强for遍历HashSet集合打印元素, 查看是否和存入顺序 一致, 是否有重复元素
代码:
public class Test {     public static void main(String[] args) {         // 创建HashSet集合, 用不用多态都行, 因为add方法不是子类特有的         Set<Integer> set = new HashSet<>();
        // 添加元素         set.add(5);         set.add(5);         set.add(4);         set.add(4);         set.add(3);         set.add(3);         set.add(2);         set.add(2);         set.add(1);         set.add(1);
        // 增强for遍历         for (Integer integer : set) {             System.out.println(integer);  // 1 2 3 4 5         }
    } } HashSet原理: 哈希值
知识点: 哈希表
int hashCode()   
什么是哈希值, 哈希值有什么作用  Object类中的 hashCode() 方法有什么作用
总结:
哈希值:     一个十进制数值, 一般是通过将该对象的内部地址转换成一个整数来实现的
public native int hashCode();     可以调用系统本地代码(C/C++)计算出一个对象地址的哈希值      hashCode()方法的作用     方法内部的算法用于将对象计算为一个哈希值, 便于根据哈希值比较对象是否"相等"     哈希值主要是为了提高对象存储在 哈希表 中的效率      注意:     1. 如果我们不满意Object中的哈希值计算方法, 可以重写hashCode()方法.         但在Java代码中不能直接重写带有 native 的方法, 重写时应该将 native 去掉             @Override             public int hashCode() {}     2. hashCode() 方法有可能将"不同的对象"计算出"相同的哈希值", 这称为"哈希冲突", 在出现冲突后, 一 般再通过 equals() 方法来继续判断对象是否"相等"                  "重地"  "通话" 补充:
HashSet原理: 哈希表结构 知识点: JDK 8以前, 哈希表是什么结构  JDK 8及之后, 哈希表是什么结构
总结:
哈希表:     JDK 8以前   : 哈希表 = 数组 + 链表     JDK 8及之后 : 哈希表 = 数组 + 链表或红黑树     数组中存储的每个元素, 是哈希值相同的一组节点的链表或红黑树
补充:
HashSet原理: 存储元素不重复的原理 知识点: HashSet集合是如何保证添加元素时不能重复的
总结:
HashSet集合保证添加元素不重复的原理:
    调用 add(E e) 添加元素时, 先调用 hashCode() 获取哈希值, 和当前HashSet集合中的元素比较         如果哈希值不同, 则认为元素不重复, 添加, 并返回true         如果哈希值相同, 则有可能是哈希冲突, 所以继续调用元素的 equals() 方法和所有哈希值相同的元素 比较             如果 equals() 比较所有元素都没有相同的, 则认为元素不重复, 添加, 并返回true             如果 equals() 比较出有相同的元素, 则认为元素重复, 不添加, 并返回false
补充:
HashSet存储自定义元素的去重 知识点: 我们自定义的JavaBean对象存入HashSet时, 想根据属性值保证不重复, 应该怎么做
总结:
自定义JavaBean对象实现在HashSet中去重:     JavaBean默认继承Object类中的 hashCode() 和 equals() 方法, 都是根据对象地址值判断是否重复的     要根据属性值判断是否重复, 应该在JavaBean类中重写 hashCode() 和 equals() 方法, 使其按照属性值 比较 补充:
5分钟练习: 自定义Person类存入HashSet实现去重
需求: 定义Person类:     私有成员变量: 姓名String name, 年龄int age     生成无参/有参构造, set/get方法, toString()方法     生成 hashCode() 和 equals() 方法 定义测试类     创建3个Person对象, 其中2个对象的姓名和年龄均相同, 另外1个对象姓名或年龄不同     创建HashSet集合, 存入3个Person对象, 打印HashSet集合, 查看是否去重 代码:
public class Person {
    private String name;     private int age;
    public Person() {     }
    public Person(String name, int age) {         this.name = name;         this.age = age;     }
    public String getName() {         return name;     }
    public void setName(String name) {         this.name = name;     }
    public int getAge() {         return age;     }
    public void setAge(int age) {         this.age = age;     }
    @Override
    public String toString() {         return "Person{" +                 "name='" + name + '\'' +                 ", age=" + age +                 '}';     }
    // 生成hashCode()和equals()方法, 根据属性值判断是否重复, 用于存储HashSet去重     @Override     public boolean equals(Object o) {         if (this == o) return true;         if (o == null || getClass() != o.getClass()) return false;         Person person = (Person) o;         return age == person.age &&                 Objects.equals(name, person.name);     }
    @Override     public int hashCode() {         return Objects.hash(name, age);     } }
public class Test {     public static void main(String[] args) {         // 创建3个Person对象         Person p1 = new Person("张三", 13);         Person p2 = new Person("张三", 13);         Person p3 = new Person("张三", 55); // 年龄不同
        // 创建HashSet集合         HashSet<Person> set = new HashSet<>();         set.add(p1);         set.add(p2);         set.add(p3);
        // 打印集合, 查看是否去重         System.out.println(set);         // [Person{name='张三', age=55}, Person{name='张三', age=13}]     } }
LinkedHashSet集合 知识点: LinkedHashSet有什么特点  LinkedHashSet底层是什么数据结构
总结:
LinkedHashSet特点:     1. 元素存取有序 (存入和取出顺序一致)     2. 元素不可重复     3. 没有索引      LinkedHashSet底层数据结构:     哈希表 + 链表   (也就是: 数组 + 链表或红黑树 + 链表)     其中, 哈希表用于存储数据, 额外的链表用于记录元素添加时的先后顺序, 以便在获取元素时保持顺序一 致 补充:
总结: 什么时候用List, 什么时候用Set?     要存储的元素可以重复的, 用List集合:         增删少, 用ArrayList         增删多, 用LinkedList     要存储的数据要求不重复, 或者相对一个集合去重, 用Set集合:         不要求存取顺序一致, 用HashSet         要求存取顺序一致, 用LinkedHashSet 5分钟练习: 使用LinkedHashSet存储元素 需求:  创建LinkedHashSet对象, 存储 5,5,4,4,3,3,2,2,1,1, 使用增强for遍历LinkedHashSet集合打印元素, 查看是 否和存入顺序一致
代码:
可变参数 知识点: 什么是可变参数  可变参数用在哪里, 格式是什么
可变参数的本质是什么  可变参数可以传递的参数个数有什么要求  可变参数的定义位置有什么要求
总结:
可变参数:     JDK 5 出现. 指同一个类型参数个数可变的参数     可变参数的本质就是一个"数组"          格式: 用在方法的参数中         修饰符 返回值类型 方法名(int... 变量名) {             // 可以直接将 变量名 当作 数组名 使用         }         方法名();
注意事项:     1. 可变参数可以传递的参数个数, 可以是 0个, 1个, 多个     2. 一个方法的参数列表中, 只能有一个可变参数     3. 如果方法的参数有多个, 可变参数必须写在参数列表的后 补充:
Collections集合工具类 Collections集合工具类: addAll(), shuffle() 知识点: Collections集合工具类的常用方法有哪些
总结:
java.util.Collections类: 操作集合的工具类     // 静态方法     static <T> boolean addAll(Collection<? super T> c, T... elements):往集合中添加一些元素     static void shuffle(List<?> list): 打乱集合顺序     static <T> void sort(List<T> list): 将集合中元素按照默认规则排序     static <T> void sort(List<T> list,Comparator<? super T> c):将集合中元素按照指定规则排序 补充:
5分钟练习: 测试addAll()和shuffle()方法 需求:  创建ArrayList集合, 使用Collections.addAll()方法, 向集合中添加1,2,3,4,5  然后调用shuffle()方法打乱该集合的顺序, 打印集合查看效果
代码:
public class Test {     public static void main(String[] args) {         // 创建ArrayList集合         ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list, 1, 2, 3, 4, 5);
        System.out.println(list);  // [1, 2, 3, 4, 5]
        // 打乱         Collections.shuffle(list);
        // 查看打乱后的结果         System.out.println(list);  // [4, 2, 3, 1, 5]     } } Collections集合工具类: sort(List<T> list) 知识点: sort(List<T> list)方法按照什么规则将元素排序  是不是所有类型的元素都能排序  该方法有什么使用前提  自定义JavaBean对象要想排序, 需要怎么做
总结:
sort(List<T> list): 默认按照"升序"将元素排序     数字, 字母, 都可以按照升序排序      自定义JavaBean对象默认不能排序, 因为不知道如何比较哪个对象大, 哪个对象小
自定义JavaBean对象要想排序, 需要实现 Comparable<E> 接口, 重写 int compareTo(E e) 方法     规则:         this-参数: 升序(从小到大)         参数-this: 降序(从大到小) 补充:
5分钟练习: 实现Person排序
需求: 定义Person类, 实现Comparable接口, 泛型为Person:     私有成员变量: 姓名String name, 年龄int age     生成无参/有参构造, set/get方法, toString()     重写int compareTo(E e)方法         方法内部根据Person对象的年龄计算大小 定义测试类     创建3个Person对象, 分别为:         李四, 14         张三, 13         王五, 15     创建ArrayList集合, 存储3个Person对象     调用 Collections.sort() 方法, 对集合排序, 然后使用增强for遍历输出结果, 查看是否排序 代码:
public class Person implements Comparable<Person> {  // 让Person自身具有可比较性
    private String name;     private int age;
    public Person() {     }
    public Person(String name, int age) {         this.name = name;         this.age = age;     }
    public String getName() {         return name;
    }
    public void setName(String name) {         this.name = name;     }
    public int getAge() {         return age;     }
    public void setAge(int age) {         this.age = age;     }
    @Override     public String toString() {         return "Person{" +                 "name='" + name + '\'' +                 ", age=" + age +                 '}';     }
    @Override     public int compareTo(Person o) {         /*         规则:             this-参数: 升序从小到大             参数-this: 降序从大到小          */         // 按照Person对象的年龄升序排序 //        return this.getAge() - o.getAge();
        // 按照Person对象的年龄降序排序         return o.getAge() - this.getAge();     } }
public class Test {     public static void main(String[] args) {         // 创建3个Person对象         Person p1 = new Person("李四", 14);
        Person p2 = new Person("张三", 13);         Person p3 = new Person("王五", 15);
        // 将3个对象存入集合         ArrayList<Person> list = new ArrayList<>();         list.add(p1);         list.add(p2);         list.add(p3);
        System.out.println("排序前:" + list);         // 排序         Collections.sort(list);         System.out.println("排序后:" + list);
    } } Collections集合工具类: sort(List<T> list, Comparator<? super T> ) 知识点:
sort(List<T> list,Comparator<? super T> c) 方法的第二个参数是什么, 如何使用 Comparable接口和Comparator接口有什么区别 自定义JavaBean对象要想利用该方法排序, 需要怎么做 总结:
Comparable接口和Comparator接口区别     Comparable: 让JavaBean自身具有可比较性 (自己和其他人比)     Comparator: 定义一个比较器类, 用比较器对象比 (让第三个人来帮两个人比较)
Comparator使用方式:     定义类作为比较器, 实现Comparator<E>接口, 重写 int compare(E o1, E o2) 方法, 泛型为要比较的元 素的类型     在Collections.sort(List<T> list,Comparator<? super T> c)方法中传入自定义比较器对象     规则:         o1-o2: 升序(从小到大)         o2-o1: 降序(从大到小) 补充:
5分钟练习: 使用Comparator对Person集合排序
需求: 定义Person类:     私有成员变量: 姓名String name, 年龄int age     生成无参/有参构造, set/get方法, toString() 定义测试类     创建3个Person对象, 分别为:         李四, 14         张三, 13         王五, 15     创建ArrayList集合, 存储3个Person对象     调用Collections.sort(List<T> list,Comparator<? super T> c)方法, 对集合排序, 比较器使用匿名内 部类对象方式, 按照Person对象的年龄排序     然后使用增强for遍历输出结果, 查看是否排序 代码:
public class Person {
    private String name;     private int age;
    public Person() {     }
    public Person(String name, int age) {         this.name = name;         this.age = age;     }
    public String getName() {         return name;     }
    public void setName(String name) {         this.name = name;     }
    public int getAge() {
        return age;     }
    public void setAge(int age) {         this.age = age;     }
    @Override     public String toString() {         return "Person{" +                 "name='" + name + '\'' +                 ", age=" + age +                 '}';     } }
public class Test {     public static void main(String[] args) {         // 创建3个Person对象         Person p1 = new Person("李四", 14);         Person p2 = new Person("张三", 13);         Person p3 = new Person("王五", 15);
        // 创建集合添加元素         ArrayList<Person> list = new ArrayList<>();         list.add(p1);         list.add(p2);         list.add(p3);
        System.out.println("排序前:" + list);         // 对集合排序         Collections.sort(list, new Comparator<Person>() {             @Override             public int compare(Person o1, Person o2) {                 /*                 规则:                     o1-o2: 升序                     o2-o1: 降序                  */                 // 按照年龄升序 //                return o1.getAge() - o2.getAge();
                // 按照年龄降序                 return o2.getAge() - o1.getAge();             }         });         System.out.println("排序后:" + list);     } } 今日API
java.util.List<E>接口:     // 常用特有成员方法 (都是按照索引来操作的)     public void add(int index, E element): 将指定的元素, 添加到该集合中的指定位置上     public E get(int index): 返回集合中指定位置的元素     public E remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素     public E set(int index, E element): 用指定元素替换集合中指定位置的元素, 返回值的更新前的元素
java.util.LinkedList<E>类: 链表结构, 查询慢, 增删快     // 特有成员方法(主要操作开头和末尾元素)     void addFirst(E e): 将指定元素插入此列表的开头     void addLast(E e): 将指定元素添加到此列表的结尾     E getFirst(): 返回此列表的第一个元素     E getLast(): 返回此列表的后一个元素     E removeFirst(): 移除并返回此列表的第一个元素     E removeLast(): 移除并返回此列表的后一个元素     E pop(): (其实就是removeFirst())从此列表所表示的堆栈处弹出一个元素 栈stack     void push(E e): (其实就是addFirst())将元素推入此列表所表示的堆栈      java.util.Collections类: 操作集合的工具类     // 静态方法     static <T> boolean addAll(Collection<T> c, T... elements):往集合中添加一些元素     static void shuffle(List<?> list) :打乱集合顺序     static <T> void sort(List<T> list) :将集合中元素按照默认规则排序     static <T> void sort(List<T> list,Comparator<? super T> c):将集合中元素按照指定规则排序 单列集合体系: Collection接口: 单列集合的根接口, 规定了公共的功能    |    |_ List接口: 元素存取有序, 可重复, 有索引    |  |_ Vector类: 底层数组, 有索引, 内存空间连续分配, 查询快, 增删慢, 线程安全, 效率低
  |  |_ ArrayList类: 底层数组, 有索引, 内存空间连续分配, 查询快, 增删慢, 线程不安全, 效率高    |  |_ LinkedList类: 底层链表, 查询慢, 增删快    |  |_ 遍历    |    - toArray(): 可以    |    - 普通for: 可以    |    - 增强for: 可以    |    - 迭代器: 可以    |    |_ Set接口: 元素不可重复, 无索引      |_ HashSet类: 底层哈希表, 元素无序, 元素不可重复(用hashCode()和equals()方法来判断)      |  |_ LinkedHashSet类: 哈希表+链表, 同时具有HashSet的元素不重复, 链表存取有序的特点      |      |_ TreeSet类: 底层红黑树结构(存入元素时就会按照元素自然顺序排序).      |        |_ 遍历        - toArray(): 可以        - 普通for: 不可以, 没有索引, 不能用!        - 增强for: 可以        - 迭代器: 可以
今日目标 能够说出List集合特点
1. 元素存取有序 2. 有索引 3. 元素可以重复 能够说出常见的数据结构
栈 队列 数组 链表 红黑树 哈希表 = 数组 + 链表/红黑树 能够说出数组结构特点 查询快 增删慢 能够说出栈结构特点
先进后出 入口出口是同一个 能够说出队列结构特点
先进先出 入口出口在两侧 能够说出单向链表结构特点




0 个回复

您需要登录后才可以回帖 登录 | 加入黑马