🍬 博主介绍
👨🎓 博主介绍:大家好,我是 hacker-routing ,很高兴认识大家~
✨主攻领域:【渗透领域】【应急响应】 【Java】 【VulnHub靶场复现】【面试分析】
🎉点赞➕评论➕收藏 == 养成习惯(一键三连)😋
🎉欢迎关注💗一起学习👍一起讨论⭐️一起进步📝文末有彩蛋
🙏作者水平有限,欢迎各位大佬指点,相互学习进步!
目录
HashSet、LinkedHashSet详解
集合体系结构
- list系列集合:添加的元素是有序、可重复、有索引
- set系列集合:添加的元素是无序、不重复、无索引
set系列集合
无序:存取顺序不一致
不重复:可以去除重复
无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素
set集合的实现类
Hashset:无序、不重复、无索引
LinkedHashSet:不有序、不重复、无索引
Treeset:可排序、不重复、无索引
set接口中的方法上基本上与colection的API一致。
Collection
set接口的简单用法
package myset;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.function.Consumer;
public class set1 {
public static void main(String[] args) {
/*
利用Set系列的集合,添加字符串,并使用多种方式遍历。
迭代器
增强for
Lambda表达式
*/
//1、创建一个set集合的对象
Set<String> s = new HashSet<>();
//2、添加元素
boolean r1 = s.add("张三");
boolean r2 = s.add("王五");
//如果当前元素是第一次添加,那么可以添加成功,返回true
//如果当前元素是第二次添加,那么添加失败,返回false
//3、打印集合
// System.out.println(r1);//true
// System.out.println(r2);//true
// System.out.println(s);//[张三]
//迭代器遍历
/* Iterator<String> it = s.iterator();
while (it.hasNext()){
String str = it.next();
System.out.println(str);
}*/
//增强for
// for (String str : s) {
// System.out.println(str);
// }
//lambda表达式
s.forEach(str -> System.out.println(str));
}
}
hashset底层原理
- HashSet集合底层采取哈希表存储数据
- 哈希表是一种对于增删改查数据性能都较好的结构
哈希表组成
JDK8之前:数组+链表
JDK8开始:数组+链表+红黑树
哈希值
- 根据hashcode方法算出来的int类型的整数
- 该方法定义在0bject类中,所有对象都可以调用,默认使用地址值进行计算
- 一般情况下,会重写hashcode方法,利用对象内部的性值计算哈希值
对象的哈希值特点
- 如果没有重写hashcode方法,不同对象计算出的哈希值是不同的
- 如果已经重写hashcode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的
- 但是在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样。(哈希碰撞)
上代码详解:
package myset;
public class set2 {
public static void main(String[] args) {
/*
哈希值:
对象的整数表现形式
1. 如果没有重写hashCode方法,不同对象计算出的哈希值是不同的
2. 如果已经重写hashcode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的
3. 但是在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样。(哈希碰撞)
*/
//1.创建对象
student1 s1 = new student1("zhangsan",23);
student1 s2 = new student1("zhangsan",23);
//2.如果没有重写hashCode方法,不同对象计算出的哈希值是不同的
// 如果已经重写hashcode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的
System.out.println(s1.hashCode());//-1461067292
System.out.println(s2.hashCode());//-1461067292
//在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样。
//哈希碰撞
System.out.println("abc".hashCode());//96354
System.out.println("acD".hashCode());//96354
}
}
Hashset JDK8以后底层原理
练习:利用HashSet集合去除重复元素
需求:创建一个存储学生对象的集合,存储多个学生对象。
使用程序实现在控制台遍历该集合。
要求:学生对象的成员变量值相同,我们就认为是同一个对象。
package myset;
import java.util.HashSet;
public class set3 {
public static void main(String[] args) {
/* 需求:创建一个存储学生对象的集合,存储多个学生对象。
使用程序实现在控制台遍历该集合。
要求:学生对象的成员变量值相同,我们就认为是同一个对象
*/
//1.创建三个学生对象
student s1 = new student("zhangsan",23);
student s2 = new student("lisi",24);
student s3 = new student("wangwu",25);
student s4 = new student("zhangsan",23);
//2、创建集合用来添加学生
HashSet<student> hs = new HashSet<>();
//3、添加元素
System.out.println(hs.add(s1));
System.out.println(hs.add(s2));
System.out.println(hs.add(s3));
System.out.println(hs.add(s4));
//4、打印集合
System.out.println(hs);
}
}
JavaBean类:student
set3.Java执行结果如下:
LinkedHashSet底层原理
package myset;
import java.util.LinkedHashSet;
public class linkedhashset {
public static void main(String[] args) {
//1.创建4个学生对象
student s1 = new student("zhangsan",23);
student s2 = new student("lisi",24);
student s3 = new student("wangwu",25);
student s4 = new student("zhangsan",23);
//2.创建集合的对象
LinkedHashSet<student> lhs = new LinkedHashSet<>();
//3.添加元素
System.out.println(lhs.add(s3));
System.out.println(lhs.add(s2));
System.out.println(lhs.add(s1));
System.out.println(lhs.add(s4));
//4.打印集合
System.out.println(lhs);
}
}
Treeset第一种排序方式超详细讲解
Treeset的特点:
-
不重复、无索引、可排序
-
可排序:按照元素的默认规则(有小到大)排序。
-
Treeset集合底层是基红黑树的数据结构实现排序的,增删改查性能都较好。
感情都在代码里!!!
package myset;
import java.util.Iterator;
import java.util.TreeSet;
public class treset1 {
public static void main(String[] args) {
/*
*
* 需求:利用TreeSet存储整数并进行排序
*
* */
//1.创建TreeSet集合对象
TreeSet<Integer> ts = new TreeSet<>();
//2、添加元素
ts.add(3);
ts.add(4);
ts.add(2);
ts.add(1);
ts.add(5);
//3、打印集合
// System.out.println(ts);
//4、遍历集合(三种遍历)
//迭代器
Iterator<Integer> it = ts.iterator();
while (it.hasNext()){
Integer i = it.next();
System.out.println(i);
}
System.out.println("---------------------------");
//增强for
for (int t : ts){
System.out.println(t);
}
System.out.println("-----------------------");
//lambda表达式
ts.forEach(integer -> System.out.println(integer));
}
}
Treeset集合默认的规则
Student实现Comparable接口,重写里面的抽象方法,再指定比较规则
package myset;
import java.util.TreeSet;
public class treeset2 {
public static void main(String[] args) {
/*
需求:创建TreeSet集合,并添加3个学生对象
学生对象属性:
姓名,年龄。
要求按照学生的年龄进行排序
同年龄按照姓名字母排列(暂不考虑中文)
同姓名,同年龄认为是同一个人
方式一:
默认的排序规则/自然排序
Student实现Comparable接口,重写里面的抽象方法,再指定比较规则
*/
//1.创建三个学生对象
student s1 = new student("zhangsan",23);
student s2 = new student("lisi",24);
student s3 = new student("wangwu",25);
student s4 = new student("zhaoliu",26);
//2.创建集合对象
TreeSet<student> ts = new TreeSet<>();
//3.添加元素
ts.add(s3);
ts.add(s2);
ts.add(s1);
ts.add(s4);
//4.打印集合
System.out.println(ts);
}
}
package myset;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
public class student implements Comparable<student>{
private String name;
private int age;
public student() {
}
public student(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "student{name = " + name + ", age = " + age + "}";
}
@Override
public int compareTo(@NotNull student o) {
//指定排序的规则
//只看年龄,安装年龄的升序来进行排列
return this.getAge() - o.getAge();
}
}