JavaDay09-Set、HashSet、LinkedHashSet、TreeSet
Set
1、无序、不重复、无索引
2、方法基本与Collection一致
3、遍历方法:Iterator、增强for、Lambda表达式
- Set实现类:
1、HashSet-无序、不重复、无索引;自定义对象需要重写equals和hashCode方法
2、LinkedHashSet(HashSet的子类)-有序(双链表机制)、不重复、无索引
3、TreeSet-可排序、不重复、无索引;自定义对象需要实现Comparable接口 重写compareTo方法
哈希值:
1、如果没有重写hashCode方法,哈希值根据地址计算,不同对象的哈希值是不同的
2、重写了hashCode方法,哈希值根据属性值计算,不同对象具有相同属性值的话的哈希值是相同的
3、少部分情况下,不同属性值或者不同地址值计算出来的哈希值也有可能相同,称为哈希碰撞
HashSet
- JDK8以前:数组+链表 JDK8以后:数组+链表+红黑树
底层原理:
1、创建一个默认长度为16、默认加载因子为0.75的数组,数组名为table,加载因子是用来扩容的
2、根据元素的哈希值跟数组的长度计算出应该存入的位置
3、存入元素之前需要判断当前位置是否为null,如果为null则直接存入
4、如果不为null,则表示有元素,调用equals方法比较属性值
5、属性值一样:不存 属性值不一样:挂在下面,形成链表 - JDK8以前,新元素存入数组,老元素挂在新元素下面
- JDK8以后,新元素直接挂在老元素下面
注意:
1、JDK8以后,当链表长度超过8,并且数组长度大于等于64,链表自动转为红黑树
2、如果集合中存储的是自定义对象,那么必须重写hashCode和equals方法
LinkedHashSet
(既要数据去重又要有序)
是HashSet的子类,有序(双链表机制)、不重复、无索引。
TreeSet
-
能够实现存入集合的元素自动排序
-
默认排序规则:
1、数字类型默认从小到大
2、字符类型默认按照在ASCII中的顺序
3、自定义对象实现排序的两种规则
规则一:自定义对象通过实现Comparable接口进行排序
public class TreeSetDemo01 {
public static void main(String[] args) {
Teacher tea1 = new Teacher("zhangSan", 35);
Teacher tea2 = new Teacher("lisi", 25);
Teacher tea3 = new Teacher("wangwu", 29);
Teacher tea4 = new Teacher("wangliu", 26);
TreeSet<Teacher> tree1 = new TreeSet<>();
tree1.add(tea1);
tree1.add(tea2);
tree1.add(tea3);
tree1.add(tea4);
System.out.println(tree1);
}
}
class Teacher implements Comparable<Teacher>{//存在TreeSet中需要实现Comparable接口
private String name;
private int age;
public Teacher(String name, int age) {
this.name = name;
this.age = age;
}
public String toString() {
return "Teacher{name = " + name + ", age = " + age + "}";
}
//重写Comparable接口的方法,实现自定义对象的排序
/*
this:正在添加的节点
o:已经存在的节点
compareTo的返回值:
1、负数,比当前节点小,存左边
2、正数,比当前节点大,存右边
3、0,重复数据,舍弃
*/
@Override
public int compareTo(Teacher o) {
//指定排序的规则
//希望按照年龄的升序进行排列
return this.age-o.age;
}
}
规则二:添加比较器comparator
添加比较器comparator
TreeSet<String> ts = new TreeSet<>((o1, o2)->{
int i=o1.length()-o2.length();
i = i==0?o1.compareTo(o2):i;
return i;
});
import java.util.Comparator;
import java.util.TreeSet;
//Comparator
public class TreeSetDemo02 {
public static void main(String[] args) {
TreeSet<String> ts = new TreeSet<>(new Comparator<String>() {
/*
o1:当前添加的元素
o2:已经在红黑树中存在的元素
返回值同compareTo
需求:先按照长度排序,如果长度相同 再按照首字母排序
*/
@Override
public int compare(String o1, String o2) {
int i=o1.length()-o2.length();
i = i==0?o1.compareTo(o2):i;
return i;
}
});
/* //改成lambda表达式:(只有函数式接口才能改成lambda表达式)
TreeSet<String> ts = new TreeSet<>((o1, o2)->{
int i=o1.length()-o2.length();
i = i==0?o1.compareTo(o2):i;
return i;
});
*/
ts.add("acd");
ts.add("afgsf");
ts.add("fghd");
System.out.println(ts);
}
}
注意:
如果两种规则都存在,以规则二为准。通常,自定义对象使用规则一,如果对象中已经存在默认排序规则但是不满足实际使用需求时,可以使用规则二重新创建排序规则
红黑树添加节点规则:

列表总结:
1、元素可重复-ArrayList
2、增删操作多于查询操作-LinkedList
3、元素不重复-HashSet
4、元素不重复且存取顺序一致-LinkedHashSet(效率低于HashSet)
5、元素排序-TreeSet
TreeSet小练习
import java.util.TreeSet;
public class CollectionDemo {
/*
需求:创建5个学生对象
属性:姓名、年龄、语文成绩、数学成绩、英语成绩
按照总分从高到低输出到控制台
如果总分一样,按照语文成绩排
如果语文一样,按照数学成绩排
如果数学一样,按照英语成绩排
如果英语一样,按照年龄排
如果年龄一样,按照姓名的字母顺序排
如果都一样,认为是同一个学生,不存
*/
public static void main(String[] args) {
Student stu1 = new Student("zhangdan", 23, 99, 99, 100);
Student stu2 = new Student("hangdandan", 24, 98, 98, 90);
Student stu3 = new Student("changdanzhi", 22, 99, 95, 92);
Student stu4 = new Student("zhangdandong", 21, 93, 99, 91);
Student stu5 = new Student("shangdanfeng", 20, 96, 94, 88);
TreeSet<Student> ts = new TreeSet<>();
ts.add(stu1);
ts.add(stu2);
ts.add(stu3);
ts.add(stu4);
ts.add(stu5);
for (Student t : ts) {
System.out.println(t);
}
}
}
package treeSet;
import javax.naming.Name;
public class Student implements Comparable<Student>{
private String Name;
private int age;
private int scoreChinese;
private int scoreMath;
private int scoreEnglish;
public Student(String Name, int age, int scoreChinese, int scoreMath, int scoreEnglish) {
this.Name = Name;
this.age = age;
this.scoreChinese = scoreChinese;
this.scoreMath = scoreMath;
this.scoreEnglish = scoreEnglish;
}
/**
* 获取
* @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;
}
/**
* 获取
* @return scoreChinese
*/
public int getScoreChinese() {
return scoreChinese;
}
/**
* 设置
* @param scoreChinese
*/
public void setScoreChinese(int scoreChinese) {
this.scoreChinese = scoreChinese;
}
/**
* 获取
* @return scoreMath
*/
public int getScoreMath() {
return scoreMath;
}
/**
* 设置
* @param scoreMath
*/
public void setScoreMath(int scoreMath) {
this.scoreMath = scoreMath;
}
/**
* 获取
* @return scoreEnglish
*/
public int getScoreEnglish() {
return scoreEnglish;
}
/**
* 设置
* @param scoreEnglish
*/
public void setScoreEnglish(int scoreEnglish) {
this.scoreEnglish = scoreEnglish;
}
public String toString() {
return "Student{Name = " + Name + ", age = " + age + ", scoreChinese = " + scoreChinese + ", scoreMath = " + scoreMath + ", scoreEnglish = " + scoreEnglish + "}";
}
//通过规则一实现自定义对象在TreeSet中排序
@Override
public int compareTo(Student o) {
int scoreAll=this.getScoreChinese()+this.getScoreMath()+this.getScoreEnglish();
int scoreO=o.getScoreChinese()+o.getScoreMath()+o.getScoreEnglish();
/* 方法一:
if (scoreO-scoreAll!=0){
return scoreO-scoreAll;
} else if (this.getScoreChinese()-o.getScoreChinese()!=0) {
return this.getScoreChinese()-o.getScoreChinese();
}else if (this.getScoreMath()-o.getScoreMath()!=0) {
return this.getScoreMath()-o.getScoreMath();
}else if (this.getScoreEnglish()-o.getScoreEnglish()!=0) {
return this.getScoreEnglish()-o.getScoreEnglish();
}else if (this.getAge()-o.getAge()!=0) {
return this.getAge()-o.getAge();
}else {
return this.getName().compareTo(o.getName());
}*/
//方法二:
int i=scoreO-scoreAll;
i=i==0?this.getScoreChinese()-o.getScoreChinese():i;
i=i==0?this.getScoreMath()-o.getScoreMath():i;
i=i==0?this.getScoreEnglish()-o.getScoreEnglish():i;
i=i==0?this.getAge()-o.getAge():i;
i=i==0?this.getName().compareTo(o.getName()):i;
return i;
}
}

浙公网安备 33010602011771号