Java从入门到放弃17—set集合/HashSet/LinkedHashSet/TreeSet
01 set集合
set集合元素唯一(不包含重复元素),无序(存取顺序不一致)
02 HashSet集合
HashSet 底层数据结构是哈希表,是元素为链表的数组,具有链表和数组的特点。HashSet不是线程安全的,集合元素可以是null。
初始容量16,加载因子0.75。
HashSet集合能够保证元素的唯一性是依靠元素类重写hashCode()方法和equals()方法来保证的,如果元素类不重写该方法,则存储该元素的集合不保证元素唯一。
HashSet底层用的是HashMap来存元素的。
hashCode()决定索引位置,如果该方法返回一个死值,会造成碰撞次数太多,效率太低。合理地重写hashCode()能有效减少碰撞次数。(对象之间对比的次数)
//以学生类为例,重写hashCode方法
@Override
public int hashCode() {
return this.name.hashCode() + this.age * 11;
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
//String和integer类对hashCode和equals方法已经重写
alt+insert选择equals和hashcode快速重写
03 LinkerHashSet集合
LinkedHashSet 底层数据结构是链表和哈希表,元素有序且唯一,链表保证了元素有序(存取顺序一致),哈希表保证了元素唯一。
public class MyTest {
public static void main(String[] args) {
LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("A");
linkedHashSet.add("B");
linkedHashSet.add("D");
linkedHashSet.add("E");
linkedHashSet.add("C");
linkedHashSet.add("E");
linkedHashSet.add("C");
linkedHashSet.add("E");
linkedHashSet.add("C");
for (String s : linkedHashSet) {
System.out.print(s+"\t");
}
}
}
//运行结果 A B C D E C
04 TreeSet集合
TreeSet 底层数据结构是二叉数,元素唯一,最大的特点是能够对元素进行排序。TreeSet不允许存null值TreeSet 排序方式分为自然排序和比较器排序。具体使用哪种排序由调用的构造方法决定。空参构造使用的是自然排序,有参构造使用的比较器排序。
TreeSet()
构造一个新的空 set,该 set 根据其元素的自然顺序进行排序。
TreeSet(Comparator < ? super E > comparator)
构造一个新的空 TreeSet,它根据指定比较器进行排序。
自然排序要求元素必须实现一个Comparable接口并重写里面的compareTo方法。(String重写了compareTo方法,返回的是正负零。)
class M implements Comparable{
@Override
public int compareTo(Object o) {
//按需求重写逻辑
return 0;
}@override
}
自然排序示例:
public class MyTest {//测试类
public static void main(String[] args) {
//按照学生的年龄大小来排序
Student s1 = new Student("John", 21);
Student s2 = new Student("Snow", 22);
Student s3 = new Student("John", 21);
TreeSet<Student> treeSet = new TreeSet<>();//使用无参构造则采用自然排序方法
treeSet.add(s1);
treeSet.add(s2);
treeSet.add(s3);
for (Student student : treeSet) {
System.out.println(student);
}
}
}
//运行结果:Student{name='John', age=21}
Student{name='Snow', age=22}
public class Student implements Comparable<Student> {// 元素类 必须实现Comparable接口
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 s) {//重写compareTo方法
//比较逻辑按照年龄大小来排序
int num1 = this.age - s.age;
//年龄相同时并不能说明是同一个对象,要继续比较姓名
int num2 = num1 == 0 ? this.name.compareTo(s.name) : num;
return num2;
}
}
比较器排序要求元素实现Comparator接口和compare方法,可以采用匿名内部类来做
public class MyTest{//测试类
public static void main(String[] args){
Student stu1 = new Student("John",18);
Student stu2 = new Student("Edwards",23);
student stu3 = new Student("jack",22);
TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student s1,Student s2){
int num1=s1.getAge()-s2.getAge();
int num2=num1==0?s1.getName().compareTo(s2.getName()):num1;
return num2;
}
});//有参构造
treeSet.add(stu1);
treeSet.add(stu2);
treeSet.add(stu3);
for(Student s : treeSet){
System.out.println(s);
}
}
}
//运行结果:Student{name='John', age=18}
Student{name='jack', age=22}
Student{name='Edwards', age=23}
public class 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 +
'}';
}
}
案例练习1
//随机产生十个不重复的,范围在0-20的数
public class Test{
public static void main(String[] args){
Random random=new Random();
LinkedSet<Integer> linkedSet = new LinkedSet<>();
while(linkedSet.size()<10){
int num = random.nextInt(20)+1;
linkedSet.add(num);
}
System.out.println(set);
}
}
案例练习2
//去除list集合里的重复元素
public class MyTest5 {
public static void main(String[] args) {
ArrayList<Integer> integers = new ArrayList<>();
integers.add(12);
integers.add(12);
integers.add(12);
integers.add(10);
integers.add(11);
integers.add(14);
integers.add(16);
integers.add(88);
HashSet<Integer> integers1 = new HashSet<>(integers);
System.out.println(integers1);
}
}
案例练习3
//需求:键盘录入3个学生信息(姓名, 语文成绩, 数学成绩, 英语成绩), 按照总分从高到低输出到控制台。
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 this.chineseScore + mathScore + englishScore;
}
}
//测试类
public class Test{
public static void main(String[] args){
TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>(){
@override
public int compare(Student s1,Student s2){
int num1=s1.getTotalScore()-s2.getTotalScore();
int num2=num1==0?s1.getName().compareTo(s2.getName()):num1;
return num2;
}
});
int i=1;
while(i<=3){
Scanner sc = new Scanner(System.in);
System.out.println("请输入第" + i + "个学生的姓名");
String name = sc.nextLine();
student.setName(name);
System.out.println("请输入" + name + "的语文成绩");
int yw = sc.nextInt();
System.out.println("请输入" + name + "的数学成绩");
int sx = sc.nextInt();
System.out.println("请输入" + name + "的英语成绩");
int yy = sc.nextInt();
Student stu = new Student(name,yw,sx,yy);
treeSet.add(stu);
}
for(Student s : treeSet){
System.out.println(s.getName+"|"s.getChineseScore()+"|"+s.getMathScore()+"|"+s.getEnglishScore()+"|"+s.getTotalScore())
}
}
}