第二十二天 treeset
知识点回顾:
Set 接口:元素唯一
//HashSet:元素无序(存的顺序和取的顺序不一致)且唯一(不允许重复元素),底层数据结构是哈希表(数组 +链表 JDK1.7 JDK1.8之后数组+链表+二叉树)
//HashSet 能够保证元素的唯一性,是靠元素重新hashCode和equals方法来保证的,如果元素不重写,则无法保证。
//合理的重写hashCode方法的是为了减少碰撞
//LinkedHashSet 元素有序且唯一 底层数据结构是链表加哈希表,链表保证了有序,哈希表保证唯一。
//TreeSet:元素唯一,且能对元素进行排序。
//自然排序:你使用空参构造,使用的就是自然排序,自然排序对元素有要求,要求元素要实现 Comparable 重写该接口中的 compareTo()
1.TreeSet存储自定义对象并遍历练习1(掌握)
注意自然排序 此对象 必须实现Comparable接口 否则报错
A:案例演示: TreeSet存储自定义对象并遍历练习1
按照年龄进行排序
年龄就是主要条件
次要条件就是姓名
//先比较年龄
int num=this.age-obj.age;
//年龄相同再比较姓名
int num2=(num==0)?this.name.compareTo(obj.name):num;
最后返回 num2
public static void main(String[] args) {
//TreeSet:元素唯一,且能对元素进行排序。
//自然排序:你使用空参构造,使用的就是自然排序,自然排序对元素有要求,要求元素要实现 Comparable 重写该接口中的 compareTo()
//根据compareTo() 方法的返回值的正负0 来决定元素在二叉树中的放置位置。
//String 类 Integer 类 都实现了 Comparable
//比较器排序
//采用自然排序:按照学生的姓名长度来排序
TreeSet<Student> treeSet = new TreeSet<>();
treeSet.add(new Student("乔布斯",50));
treeSet.add(new Student("尼古拉斯赵四", 57));
treeSet.add(new Student("刘能", 57));
treeSet.add(new Student("谢大脚", 57));
treeSet.add(new Student("东北狠人彪哥药匣子", 23));
treeSet.add(new Student("剪刀手爱德华", 97));
treeSet.add(new Student("王祖贤", 47));
treeSet.add(new Student("王菲", 17));
treeSet.add(new Student("王菲", 17));
treeSet.add(new Student("王菲", 87));
for (Student student : treeSet) {
System.out.println(student.getName()+"==="+student.getAge());
}
}
学生类中重写的compareTo方法
@Override
public int compareTo(Student student) {
//根据姓名的长度排序
int num=this.name.length()-student.name.length();
//姓名长度一样,并不能说明是同一个对象,还得比较姓名的内容一样不?
int num2=num==0?this.name.compareTo(student.name):num;
//姓名长度一样,姓名字面内容一样,也不能说明是同一个对象,还得比较一下年龄
int num3=num2==0?this.age-student.age:num2;
return num3; //正 负 0
}
2.TreeSet存储自定义对象并遍历练习2(掌握)
A:案例演示: TreeSet存储自定义对象并遍历练习2
按照姓名的长度进行排序
主要条件是姓名的长度
然后是姓名
然后是年龄
//先比较姓名长度
int num=this.name.length()-obj.name.length();
//如果姓名长度一样再比较年龄
int num2=(num0)?this.age-obj.age:num;
//如果年龄相同 再比较姓名
int num3=(num20)?this.name.compareTo(obj.name):num2;
最后返回 num3
public static void main(String[] args) {
//使用比较器排序,按照姓名的长度来排序
TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int num = s1.getName().length() - s2.getName().length();
int num2=num==0?s1.getName().compareTo(s2.getName()):num;
int num3=num2==0?s1.getAge()-s2.getAge():num2;
return num3;
}
});
treeSet.add(new Student("乔布斯", 50));
treeSet.add(new Student("尼古拉斯赵四", 57));
treeSet.add(new Student("刘能", 57));
treeSet.add(new Student("谢大脚", 57));
treeSet.add(new Student("东北狠人彪哥药匣子", 23));
treeSet.add(new Student("剪刀手爱德华", 97));
treeSet.add(new Student("王祖贤", 47));
treeSet.add(new Student("王菲", 17));
treeSet.add(new Student("王菲", 17));
treeSet.add(new Student("王菲", 87));
for (Student student : treeSet) {
System.out.println(student.getName() + "===" + student.getAge());
}
}
3.TreeSet保证元素唯一和比较器排序的原理及代码实现(掌握)
A:案例演示: TreeSet保证元素唯一和比较器排序的原理及代码实现
在创建TreeSet对象的时候,传递一个比较器对象
B: 按照年龄进行排序
public static void main(String[] args) {
//Comparator 这个比较器,不光TreeSet能用,其他的有些类也能用
//可以将 Comparator 传递给 sort 方法(如 Collections.sort 或 Arrays.sort),
ArrayList<Integer> list = new ArrayList<>();
list.add(20);
list.add(220);
list.add(290);
list.add(2);
list.add(120);
list.add(201);
list.add(209);
//传入比较器,对List集合中的元素进行排序
list.sort(new Comparator<Integer>() {
@Override
public int compare(Integer a, Integer b) {
return b-a;
}
});
System.out.println(list);
System.out.println("============================");
int[] arr={20,30,90,41,33};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
System.out.println("=======================");
Integer[] arr2 = {20, 30, 90, 41, 33};
//参数2:可以传入比较器
Arrays.sort(arr2, new Comparator<Integer>() {
@Override
public int compare(Integer a, Integer b) {
return b-a; //降序排列
}
});
System.out.println(Arrays.toString(arr2));
}
4.产生10个1-20之间的随机数要求随机数不能重复(掌握)
A:案例演示
需求:编写一个程序,获取10个1至20的随机数,要求随机数不能重复。
并把最终的随机数输出到控制台。
选HashSet 可以不重复
选TreeSet 不重复还可以排序
分析:
a: 定义一个HashSet集合
b: 产生随机数,把随机数添加到集合中
c: 判断集合的长度,使用while循环实现
public static void main(String[] args) {
//需求:编写一个程序,获取10个1至20的随机数,要求随机数不能重复。
Random random = new Random();
LinkedHashSet<Integer> linkedHashSet = new LinkedHashSet<>();
while (linkedHashSet.size()<10){
int num = random.nextInt(20) + 1;
linkedHashSet.add(num);
}
System.out.println(linkedHashSet);
}
5.键盘录入学生信息按照总分排序后输出在控制台(掌握)
A:案例演示: 需求:键盘录入3个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台。
/**
* 步骤:
* a: 自定义一个学生类
* b: 创建一个TreeSet集合对象(使用比较器进行排序)
* c: 键盘录入学生的数据,然后把学生的数据封装成一个学生对象,把学生对象添加到集合中
* d: 遍历集合
*/
public static void main(String[] args) {
/* A:
案例演示:
需求:键盘录入3个学生信息(姓名, 语文成绩, 数学成绩, 英语成绩), 按照总分从高到低输出到控制台*/
TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
//按照学生的总分从高到低来排序
int num = s1.getTotalScore() - s2.getTotalScore();
//总分一样,并不能说名是同一个学生,还得比较一下姓名。
int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
return -num2; //降序排列
}
});
for (int i = 1; i <=3; i++) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入第"+i+"个学生的姓名");
String name = scanner.nextLine();
System.out.println("请输入第" + i + "个学生的语文成绩");
int yw = scanner.nextInt();
System.out.println("请输入第" + i + "个学生的数学成绩");
int sx= scanner.nextInt();
System.out.println("请输入第" + i + "个学生的英语成绩");
int yy = scanner.nextInt();
//创建学生对象,把录入的信息,封装到学生学生对象里面
Student student = new Student(name, yw, sx, yy);
//这三个对象,得找容器存起来
treeSet.add(student);
}
//按照总分高低排序,输出学生的信息。
System.out.println("名次\t姓名\t语文\t数学\t英语\t总分");
int i=0;
for (Student student : treeSet) {
System.out.println((++i)+"\t"+student.getName()+"\t"+student.getChineseScore()+"\t"+student.getMathScore()+"\t"+student.getEnglishScore()+"\t"+student.getTotalScore());
}
}
public class Student{
//姓名,语文成绩,数学成绩,英语成绩
private String name;
private int chineseScore;
private int mathScore;
private int englishScore;
学生类
public Student() {}
public Student(String name, int chineseScore, int mathScore, int englishScore) {
this.name = name;
this.chineseScore = chineseScore;
this.mathScore = mathScore;
this.englishScore = englishScore; }
public String getName() { return name;}
public void setName(String name) { this.name = name; }
public int getChineseScore() { return chineseScore;}
public void setChineseScore(int chineseScore) {this.chineseScore = chineseScore;}
public int getMathScore() {return mathScore;}
public void setMathScore(int mathScore) {this.mathScore = mathScore;}
public int getEnglishScore() {return englishScore;}
public void setEnglishScore(int englishScore) {this.englishScore = englishScore;}
//提供一个获取总分的方法
public int getTotalScore(){return chineseScore+mathScore+englishScore;}
}