Java从入门到放弃17—set集合/HashSet/LinkedHashSet/TreeSet

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())
        }
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值