概述:Set 是一个接口,与 List 类似,都需要通过实现类来对其进行操作
Set 集合的特点
不包含重复的元素
没有带索引的方法,所以不能使用普通 for 循环遍历
demo:Set集合的使用
哈希值:是 JDK 根据对象的 地址 或者 字符串 或者 数值 计算出来的 int 类型的数值
Object 对象中就有一个方法可以获取对象的哈希值:
public int hashCode()
对象的哈希值特点
同一个对象多次调用 hashCode()
方法,得到的返回值是相同的
默认情况下,不同对象的哈希值是不同的
但是可以通过重写 hashCode()
方法来实现不同对象的哈希值相同
demo 测试不同类的哈希值
HashSet 集合特点
底层数据结构是哈希表
对集合的迭代顺序不做任何保证,也就是说不能保证存储和读取的顺序一直
没有带有索引为参数的方法,也就是说不能使用普通的 for 循环对其进行遍历
由于是 set 集合,所以不包含重复的元素
demo —双色球(Set)版
package com.itxiaosi.demo01;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
/**
* @Classname : demo04
* @Description : TODO 双色球 (Set版)
* @Author : lin_refuel@qq.com
*/
public class demo04 {
public static void main(String[] args) {
//随机值产生对象
Random ran = new Random();
// 蓝色球1-16
int blue = ran.nextInt(16)+1;
// 红色球 6个 1-33之间的数
// Set<Integer> red = new HashSet<>();
Set<Integer> red = new TreeSet<>();//TreeSet是默认排序的
//循环放入集合
while(red.size()<6){
int red01 = ran.nextInt(33)+1;
red.add(red01);//Set集合不能存在重复值
}
System.out.println("红球" + red);
System.out.println("篮球" + blue);
}
}
去重原理
先对比 hashCode 如果相同的话,在对比 equals 的内容,这两个方法经常需要在子类中进行重写
demo:创建一个学生类,重新Hashcode和equals
package com.itxiaosi.demo01;
import java.util.Objects;
/**
* @Classname : Student
* @Description : TODO 学生类对象
* @Author : lin_refuel@qq.com
*/
public class Student {
//学生两个基本属性
private String name; //姓名
private int age; //年龄
//两个构造方法
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//重写equals
@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);
}
//重写 hasCode
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
demo:测试去重复的学生类对象
package com.itxiaosi.demo01;
import java.util.HashSet;
/**
* @Classname : demo05
* @Description : TODO HashSet 存储不同学生对象,重写Hashcode和equals
* @Author : lin_refuel@qq.com
*/
public class demo05 {
public static void main(String[] args) {
//一个空的HashSet
HashSet<Student> stuHAS = new HashSet<>();
//调用add添加成员
stuHAS.add(new Student("黄固",22));
stuHAS.add(new Student("欧阳锋",23));
stuHAS.add(new Student("段智兴",25));
stuHAS.add(new Student("洪七公",27));
stuHAS.add(new Student("黄固",22));
//遍历stuHAS
for (Student stuHA : stuHAS) {
System.out.println(stuHA);
}
}
}
LinkedHashSet 集合特点
LinkedHashSet 是哈希表和链表实现的 Set 接口,具有可预测的迭代顺序
有链表保证元素有序,也就是说元素的存储和读取顺序是一致的
由哈希表保证元素的唯一性,也就是说没有重复的元素
demo
package com.itxiaosi.demo01;
import java.util.LinkedHashSet;
/**
* @Classname : demo06
* @Description : TODO LinkedHashSet的使用
* @Author : lin_refuel@qq.com
*/
public class demo06 {
public static void main(String[] args) {
//定义一个空的LinkedHashSet
LinkedHashSet<String> set = new LinkedHashSet<>();
//添加元素
set.add("黄固");
set.add("欧阳锋");
set.add("段智兴");
set.add("洪七公");
set.add("王重阳");
//通过迭代器进行遍历
for (String s : set) {
System.out.println(s);
}
}
}
TreeSet 集合特点
有序元素,这里的顺序不是值存储和读取的顺序,而是按照一定的规则进行排序,具体排序方式取决于实例化对象时的构造方法
TreeSet()
:根据元素的自然顺序进行排序
TreeSet(Comparator comparator)
:根据指定的比较器进行排序
没有带索引的方法,所以不能使用普通 for 循环遍历
由于是 Set 集合,所以不存在重复的元素
TreeSet是自带排序的,默认是从小到大进行排序
package com.itxiaosi.demo01;
import java.util.TreeSet;
/**
* @Classname : demo07
* @Description : TODO Tree集合的自然规则
* @Author : lin_refuel@qq.com
*/
public class demo07 {
public static void main(String[] args) {
//Tree集合
TreeSet<Integer> tree = new TreeSet<>();
//添加元素,打乱顺序
tree.add(3);
tree.add(31);
tree.add(6);
tree.add(5);
tree.add(1);
tree.add(33);
System.out.println(tree);//[1, 3, 5, 6, 31, 33]
}
}
定义一个学生类,作为Comparable接口的实现类,重写接口里面的方法CompareTo
package com.itxiaosi.demo02;
/**
* @Classname : Student
* @Description : TODO 学生类
* @Author : lin_refuel@qq.com
*/
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;
}
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 "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student o) {
//return 0; // TODO 返回值为0默认两个对像是相同的,不会进行添加
//return 1;//TODO 返回值为正数,顺序进行排序
//return -1;//TODO 返回值为负数,逆序进行排序
// TODO 按照年龄进行排序
int res = this.getAge() - o.getAge();//两个人的年龄差,年龄从小往大进行排序
//TODO 如果年龄相同,比较名字是否相同,compareTo是比较字符串大小的
return res == 0?this.getName().compareTo(o.getName()):res;
}
}
TreeSet集合是自己调用比较器的,当存储的是对象时无法直接比较,需要对象里面重写比较器
package com.itxiaosi.demo02;
import java.util.TreeSet;
/**
* @Classname : demo02
* @Description : TODO TreeSet集合存储学生类对像,设置比较器排序方式
* @Author : lin_refuel@qq.com
*/
public class demo02 {
public static void main(String[] args) {
TreeSet<Student> StuSet = new TreeSet<>();//学生类TreeSet集合
//添加学生信息
StuSet.add(new Student("Andy",17));
StuSet.add(new Student("rocky",14));
StuSet.add(new Student("lucy",15));
StuSet.add(new Student("Licinius",16));
StuSet.add(new Student("messi",17));
// 通过迭代器进行遍历
for (Student student : StuSet) {
System.out.println(student);
}
}
}
学生类对象
package com.itxiaosi.demo02;
/**
* @Classname : Student02
* @Description : TODO 学生类对象02
* @Author : lin_refuel@qq.com
*/
public class Student02 {
//定义两个学生的属性
private String name;
private int age;
public Student02(String name, int age) {
this.name = name;
this.age = age;
}
public Student02() {
}
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 "Student02{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
匿名内部类实现
package com.itxiaosi.demo02;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
/**
* @Classname : demo01
* @Description : TODO TreeSet比较学生类对象的第二种方式
* @Author : lin_refuel@qq.com
*/
public class demo01 {
public static void main(String[] args) {
//学生类集合
TreeSet<Student> StuSet = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
//按照年龄方式进行比较
int res = o2.getAge() - o1.getAge();//从大往小排序
return res == 0?o1.getName().compareTo(o2.getName()):res;
}
});
// 添加成员
StuSet.add(new Student("小白",17));
StuSet.add(new Student("卢卡",17));
StuSet.add(new Student("小蓝",18));
StuSet.add(new Student("小红",15));
StuSet.add(new Student("小白",16));
//迭代器进行遍历
Iterator<Student> it = StuSet.iterator();
while(it.hasNext())
System.out.println(it.next());
}
}