1. 数据结构
数组(ArrayList
中基于数组的实现)
多个元素之间的空间是连续的 根据索引的查询速度快: 查询数据通过地址值和索引值(list.get(i))定位,查询任意数据耗时相同 删除效率低: 可能需要把后面的数据前移 添加效率低: 可能需要把后面的数据后移,再添加元素(插队添加);或者也可能需要进行数组的扩容
单链表
链表中的节点是独立的对象,在内存中不连续,每个节点包含数据值和下一个节点的地址值 特点
查询慢,无论查询哪个数据都要从头开始找 增删相对较快
双向链表
一个节点包含三个值
头节点: 始终被记录着,头节点没有前一个节点的地址 尾节点: 始终被记录着,尾节点没有后一个节点的地址
栈
先进后出,后进先出,像弹夹 比如栈内存
队列
先进先出,后进后出,像排队 讲线程池-阻塞队列
2. Set集合
2.1 Set集合的特点
HashSet: 存取无序,不重复,无索引 LinkedHashSet: 存取有序,不重复,无索引 TreeSet: 排序,不重复,无索引
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
// Set<Integer> set = new LinkedHashSet<>();
// Set<Integer> set = new TreeSet<>();
set.add(666);
set.add(555);
set.add(555);
set.add(888);
set.add(888);
set.add(777);
set.add(777);
System.out.println(set);
}
2.2 HashSet
存储自定义类型
2.2.1 现象
需要重写equals和hashCode方法,才能去重
public class Student {
private String name;
private int age;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", 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;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
public static void main(String[] args) {
Student stu1 = new Student("张三",23);
Student stu2 = new Student("李四",24);
Student stu3 = new Student("李四",24);
Student stu4 = new Student("王五",25);
Set<Student> set = new HashSet<>();
set.add(stu1);
set.add(stu2);
set.add(stu3);
set.add(stu4);
System.out.println(set);
}
2.2.2 hashCode
方法和哈希值
Object中的hashCode方法
自定义类型默认使用父类Object中的hashCode方法
public native int hashCode();
此方法为本地方法,C++写的,采用哈希算法 此方法的返回值为int数值,也被称为哈希值 哈希值:
每个对象都可以通过hashCode方法获取 特点: 同一个对象多次调用hashCode()方法返回的哈希值是相同的。 不同的对象,它们的哈希值一般不相同,但也有可能会相同(哈希碰撞)。
重写的hashCode
方法
@Override
public int hashCode() {
// 根据成员变量的值计算的
return Objects.hash(name, age);
}
2.2.3 HashSet底层原理
JDK8
以前
数据结构: 哈希表:数组 + 链表 使用空参构造创建HashSet集合,第一次添加元素时。创建一个默认长度为16的数组,默认加载因子为0.75
加载因子: 当集合中元素的个数达到 16 * 0.75(=12) 扩容2倍 添加元素时,使用元素的哈希值和数组长度计算应存入的索引位置
判断当前索引位置是否为null
是null 存入数组 不是null 表示有元素,调用equals方法逐个比较
相同不存 不同,JDK8
以前将新元素存入数组,老元素挂在新元素的下面,形成链表
JDK8
开始
数据结构: 哈希表:数组 + 链表 + 红黑树 使用空参构造创建HashSet集合,第一次添加元素时创建一个默认长度为16的数组,默认加载因子为0.75
加载因子: 当数组中元素的个数达到 16 * 0.75 扩容2倍 添加元素时,使用元素的哈希值和数组长度计算应存入的索引位置
判断当前索引位置是否为null
是null 存入数组 不是null 表示有元素,调用equals方法逐个比较
相同不存 不同,JDK8开始-新元素挂在老元素的下面,形成链表 JDK8
开始-如果链表的长度超过8,且数组的长度>=64,自动将链表转成红黑树(提升操作数据效率)
HashSet
存储自定义类型
如果想要认为内容相同就是相同的对象
需要重写hashCode方法(通过成员变量的值计算),决定存入哈希表中数组的索引位置 需要重写equals方法(比较成员变量的值),相同就去重
2.2.4 数据结构-树形结构
整理总结
在线图形化测试用例:
https://www.cs.usfca.edu/~galles/visualization/Algorithms.html 7 4 10 2 5 1
2.3 LinkedHashSet
2.3.1 特点
2.3.2 原理
不能重复: 底层的数据结构: 哈希表 有序: 每一个元素都额外的多了一个双向链表机制,记录它前后元素的位置
2.4 TreeSet
2.4.1 特点
排序(默认升序),不重复,无索引 TreeSet存储自定义类型需要指定排序规则
自然排序: 自定义类实现Comparable接口,重写compareTo方法 比较器排序: 使用TreeSet
带参数构造方法(Comparator),在重写compare方法中指定排序规则
2.4.2 原理
数据结构: 红黑树
https://www.cs.usfca.edu/~galles/visualization/Algorithms.html 默认升序
3. Collection单列集合小结
单列集合构造方法
构造方法 说明 public ArrayList(Collection<? extends E> c) 将任意单例集合中的元素添加到新的ArrayList集合中 public LinkedList(Collection<? extends E> c) 将任意单例集合中的元素添加到新的LinkedList集合中 public HashSet(Collection<? extends E> c) 将任意单例集合中的元素添加到新的HashSet集合中 public LinkedHashSet(Collection<? extends E> c) 将任意单例集合中的元素添加到新的LinkedHashSet集合中 public TreeSet(Collection<? extends E> c) 将任意单例集合中的元素添加到新的TreeSet集合中
4. 可变参数
格式: 是一种特殊的形参,定义在方法的形参列表: 数据类型… 变量名
public void test(数据类型... 变量名){
}
public void test(int... nums){
}
特点: 调用方法时
好处: 可以灵活的接收数据 本质: 在方法的内部,本质就是一个数组 注意事项
方法的形参中,只能有一个可变参数 如果有多个参数,可变参数必须放在最后
public static void main(String[] args) {
test(); // 不传参
test(10); // 传1个参数
test(10,20,30); // 传多个参数
test(new int[]{100,200,300}); // 传一个数组
}
// public static void test(int... nums,String... strings){ // 只能有一个可变参数
// public static void test(int a, int... nums){ // 如果参数有多个,可变参数只能写在最后
public static void test(int... nums){
// 方法内部 可变参数本质是一个数组
System.out.println(nums.length);
System.out.println(Arrays.toString(nums));
System.out.println("----------------");
}
5. Collections工具类
方法名 说明 public static boolean addAll(Collection<? super T> c, T… elements) 给集合批量添加元素 public static void shuffle(List<?> list) 打乱List集合中的元素顺序 public static void reverse(List<?> list) List集合数据反转 public static void swap(List<?> list, int i, int j) List集合指定索引位置交换数据 public static boolean replaceAll(List list, T oldVal, T newVal) List集合数据替换
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
Collections.addAll(list,1,2,3,4,5,6);
System.out.println(list);
Collections.shuffle(list);
System.out.println(list);
Collections.reverse(list);
System.out.println(list);
Collections.swap(list,1,2);
System.out.println(list);
Collections.replaceAll(list,1,100);
System.out.println(list);
}
练习
模拟斗地主游戏: 做牌,洗牌,发牌,看牌 分析: 面向对象
房间
房间中有一副扑克牌(54张牌)
扑克牌有数值 3 4 5 6 7 8 9 10 J Q K A 2 扑克牌有花色 “♠”, “♥”, “♣”, “♦” “大王”,“小王” 扑克牌有大小 房间中有3个玩家(每人17张牌) 发牌时要留3张底牌
package com.itheima.test;
/**
* @Auther: Yishooo
* @Date: 2023-4-4 - 04 - 04 - 15:50
* @Description: 表示一张牌
*/
public class Card implements Comparable<Card>{
private String number;//数值
private String color;//花色
private int size;//3 4 5 6 (0 1 2 3)
public Card() {
}
public Card(String number, String color, int size) {
this.number = number;
this.color = color;
this.size = size;
}
@Override
public String toString() {
return color+number;//+"->"+size
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
@Override
public int compareTo(Card o) {
return this.size-o.size;
}
}
package com. itheima. test ;
import java. util. ArrayList ;
import java. util. Collections ;
import java. util. Comparator ;
import java. util. List ;
public class Room {
private List < Card > list = new ArrayList < > ( ) ;
private List < Card > player1 = new ArrayList < > ( ) ;
private List < Card > player2 = new ArrayList < > ( ) ;
private List < Card > player3 = new ArrayList < > ( ) ;
public Room ( ) {
init ( ) ;
System . out. println ( "洗牌前:" + list) ;
}
public void init ( ) {
String [ ] numbers = { "3" , "4" , "5" , "6" , "7" , "8" , "9" , "10" , "J" , "Q" , "K" , "A" , "2" } ;
String [ ] colors = { "♠" , "♥" , "♣" , "♦" } ;
for ( int i = 0 ; i < numbers. length; i++ ) {
for ( int j = 0 ; j < colors. length; j++ ) {
Card c = new Card ( numbers[ i] , colors[ j] , i) ;
list. add ( c) ;
}
}
Collections . addAll ( list, new Card ( "" , "小王" , numbers. length) , new Card ( "" , "大王" , numbers. length+ 1 ) ) ;
}
public void start ( ) {
Collections . shuffle ( list) ;
System . out. println ( "洗牌后:" + list) ;
for ( int i = 0 ; i < list. size ( ) - 3 ; i++ ) {
int num = i % 3 ;
switch ( num) {
case 0 : / / 发给第一个玩家
player1. add ( list. get ( i) ) ;
break ;
case 1 : / / 发给第二个玩家
player2. add ( list. get ( i) ) ;
break ;
case 2 : / / 发给第三个玩家
player3. add ( list. get ( i) ) ;
break ;
}
}
sort ( ) ;
System . out. println ( "玩家一:" + player1) ;
System . out. println ( "玩家二:" + player2) ;
System . out. println ( "玩家三:" + player3) ;
}
public void sort ( ) {
player1. sort ( ( o1, o2) -> o1. getSize ( ) - o2. getSize ( ) ) ;
player2. sort ( ( o1, o2) -> o1. getSize ( ) - o2. getSize ( ) ) ;
player3. sort ( ( o1, o2) -> o1. getSize ( ) - o2. getSize ( ) ) ;
}
}
package com. itheima. test ;
public class Demo {
public static void main ( String [ ] args) {
Room room = new Room ( ) ;
room. start ( ) ;
}
}
重点内容
掌握单列集合每种实现类的特点,使用 知道每种实现类底层原理(数据结构) 掌握可变参数的使用
预习内容