2020-08-08

本文深入探讨了集合框架的各种特性,包括Set、HashSet、LinkedHashSet和TreeSet的使用方法,以及它们在存储唯一元素和保证排序方面的原理。通过实例展示了如何利用这些集合类存储字符串、整数和自定义对象,并进行了遍历练习。
摘要由CSDN通过智能技术生成

集合框架

Set

Set集合概述及特点
  • 可通过API查看
  • 无序(存储和取出的顺序)和唯一(元素不允许重复)
HashSet存储字符串并遍历
import java.util.HashSet;
public class MyTest {
    public static void main(String[] args) {
        HashSet<String> str = new HashSet<>();
        str.add("a");
        str.add("aa");
        str.add("aa");
        str.add("aaa");
        str.add("aaaa");

        for (String s : str) {
            System.out.println(s);
            //aa
            //aaa
            //a
            //aaaa
        }
    }
}
// HashSet:底层数据结构是哈希表(JDK1.7 数组+链表 JDK1.8 优化 数组+链表+红黑树)
//元素无序(存取元素的顺序不一致)且唯一(元素不允许重复)
//HashSet集合保证元素的唯一性,是靠元素重新hashCode和equals()方法来保证的,如果元素不重写,则无法保证元素的 唯一性。

HashSet保证元素唯一性
  • HashSet 底层数据结构是哈希表
  • HashSet 不是线程安全的,集合元素可以是 null
  • 哈希表:是一个元素为链表的数组,综合了数组和链表的优点 (像新华字典一样) (JDK1.7之前)

当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的hashCode 值,然后根据 hashCode 值决定该对象在 HashSet 中的存储位置。

HashSet 集合判断两个元素相等的标准
两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。

结论:HashSet 保证元素唯一性是靠元素重写hashCode()和equals()方法来保证的,如果不重写则无法保证。

HashSet存储自定义对象保证元素唯一性
import java.util.HashSet;
public class MyTest {
    public static void main(String[] args) {
        HashSet<Student> students = new HashSet<>();
        students.add(new Student("鹿秀儿", 22));
        students.add(new Student("鹿秀儿", 22));
        students.add(new Student("鹿秀", 22));
        students.add(new Student("鹿秀儿", 19));
        for (Student student : students) {
            System.out.println(student);
            //Student{name='鹿秀儿', age=22}
            //Student{name='鹿秀', age=22}
            //Student{name='鹿秀儿', age=19}
        }
    }
}
HashSet存储自定义对象保证元素唯一性图解及代码优化

在这里插入图片描述

代码优化:为了减少比较,优化hashCode()代码写法。最终版就是自动生成即可

HashSet存储自定义对象并遍历练习
import java.util.HashSet;
import java.util.Iterator;
import java.util.function.Consumer;
public class MyTest {
    public static void main(String[] args) {
        HashSet<Student> students = new HashSet<>();
        students.add(new Student("鹿秀儿", 22));
        students.add(new Student("鹿秀儿", 22));
        students.add(new Student("鹿秀", 22));
        students.add(new Student("鹿秀儿", 19));
        //for方法遍历
        for (Student student : students) {
            System.out.println(student);
            //Student{name='鹿秀儿', age=22}
            //Student{name='鹿秀', age=22}
            //Student{name='鹿秀儿', age=19}
        }
        //forEach遍历
        students.forEach(new Consumer<Student>() {
            @Override
            public void accept(Student student) {
                System.out.println(student.getName() + "==" + student.getAge());
                //鹿秀儿==22
                //鹿秀==22
                //鹿秀儿==19
            }
        });
        //迭代器遍历
        Iterator<Student> iterator = students.iterator();
        while (iterator.hasNext()){
            Student next = iterator.next();
            System.out.println(next);
            //Student{name='鹿秀儿', age=22}
            //Student{name='鹿秀', age=22}
            //Student{name='鹿秀儿', age=19}
        }

    }
}
LinkedHashSet的概述和使用

数据结构有两个

  • 链表(保证有序)(按照添加的顺序)
  • 哈希表(保证元素唯一)

LinkedHashSet的概述:元素有序,并且唯一

import java.util.LinkedHashSet;
public class MyTest {
    public static void main(String[] args) {
        LinkedHashSet<Integer> integers = new LinkedHashSet<>();
        integers.add(44);
        integers.add(26);
        integers.add(85);
        integers.add(54);
        integers.add(86);
        integers.add(23);
        integers.add(77);
        for (Integer integer : integers) {
            System.out.print(integer+"\t");
            //与录入顺序一致
            //44  26  85  54  86  23  77
        }
    }
}
TreeSet存储Integer类型的元素并遍历

TreeSet集合的特点

  • 元素唯一,并且可以对元素进行排序

  • 排序:

    自然排序

    使用比较器排序

  • 具体使用哪一种排序取决于构造方法

import java.util.TreeSet;
public class MyTest {
    public static void main(String[] args) {
        TreeSet<Integer> integers = new TreeSet<>();
        integers.add(20);
        integers.add(18);
        integers.add(23);
        integers.add(22);
        integers.add(17);
        integers.add(24);
        integers.add(19);
        integers.add(18);
        integers.add(24);
        for (Integer integer : integers) {
            System.out.print(integer+"\t");
            //17  18  19  20  22  23  24	
        }
    }
}
//注意:使用TreeSet集合进行元素的自然排序,那么对元素有要求,要求这个元素必须实现Comparable接口 否则无法进行自然排序
//保证元素的唯一性是靠compareTo方法的返回值来确定如果返回0 表示两个元素相等则不重复存储
TreeSet保证元素唯一和自然排序的原理和图解

在这里插入图片描述

二叉树的数据结构

先存入一个树根,分两个叉,存储元素时,跟树根比较,小的放在左边,大的放在右边

如果相等就不存储,取的时候按照左中右的顺序来取

TreeSet存储自定义对象并遍历练习1
import java.util.TreeSet;
public class MyTest {
    public static void main(String[] args) {
        TreeSet<Student> students = new TreeSet<>();
        students.add(new Student("鹿秀儿", 18));
        students.add(new Student("路遥知", 17));
        students.add(new Student("赵天笑", 24));
        students.add(new Student("笑", 24));
        students.add(new Student("赵天笑", 24));
        students.add(new Student("大雄", 13));
        for (Student student : students) {
            System.out.println(student);
            //Student{name='大雄', age=13}
            //Student{name='路遥知', age=17}
            //Student{name='鹿秀儿', age=18}
            //Student{name='笑', age=24}
            //Student{name='赵天笑', age=24}
        }
    }
}

public class Student implements 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 int compareTo(Object o) {
        Student s= (Student) o;
        //先比较年龄
        int a=this.age-s.age;
        //再比较姓名
        int b=(a==0)?this.name.compareTo(s.name):a;
        return b;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
TreeSet存储自定义对象并遍历练习2
import java.util.TreeSet;

public class MyTest {
    public static void main(String[] args) {
        TreeSet<Student> students = new TreeSet<>();
        students.add(new Student("鹿秀儿", 18));
        students.add(new Student("路遥知", 17));
        students.add(new Student("赵天笑", 24));
        students.add(new Student("笑", 24));
        students.add(new Student("赵天笑", 24));
        students.add(new Student("大雄", 13));
        for (Student student : students) {
            System.out.println(student);
            //Student{name='笑', age=24}
            //Student{name='大雄', age=13}
            //Student{name='路遥知', age=17}
            //Student{name='鹿秀儿', age=18}
            //Student{name='赵天笑', age=24}
        }
    }
}

public class Student implements 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 int compareTo(Object o) {
        Student s= (Student) o;
        //先比较名字长度
        int a=this.name.length()-s.name.length();
        //再比较年龄
        int b=(a==0)?this.age-s.age:a;
        //最后比较姓名
        int c=(b==0)?this.name.compareTo(s.name):b;
        return c;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
产生10个1-20之间的随机数要求随机数不能重复
import java.util.HashSet;
import java.util.TreeSet;
public class MyTest {
    public static void main(String[] args) {
        //HashSet不重复
        HashSet<Integer> hashSet = new HashSet<>();
        for(;;){
            hashSet.add((int) (Math.random()*20+1));
            if (hashSet.size()>=10){
                break;
            }
        }
        System.out.println(hashSet);
        //TreeSet不重复并且排序
        TreeSet<Integer> treeSet = new TreeSet<>();
        for (; ; ) {
            treeSet.add((int) (Math.random()*20+1));
            if(treeSet.size()>=10){
                break;
            }
        }
        System.out.println(treeSet);
    }
}
import java.util.HashSet;
public class MyTest {
    public static void main(String[] args) {
        HashSet<Integer> hashSet = new HashSet<>();
        //while循环判断集合长度
        while(hashSet.size()<10){
            hashSet.add((int) (Math.random()*20+1));
        }
        System.out.println(hashSet);
    }
}
键盘录入学生信息按照总分排序后输出在控制台
import java.util.Scanner;
import java.util.TreeSet;
import java.util.function.Consumer;
public class MyTest {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("输入学生个数");
        int n = sc.nextInt();
        TreeSet<Student> students = new TreeSet<>();
        for (int i = 1; i <= n; i++) {
            Student s = new Student();

            System.out.println("输入第" + i + "个学生姓名");
            String name = sc.next();
            s.setName(name);

            System.out.println("输入"+name+"的语文成绩");
            int ch = sc.nextInt();
            s.setChineseScore(ch);

            System.out.println("输入"+name+"的数学成绩");
            int ma= sc.nextInt();
            s.setMathScore(ma);

            System.out.println("输入"+name+"的英语成绩");
            int en = sc.nextInt();
            s.setEnglishScore(en);

            s.setZongfen(ch+ma+en);

            students.add(s);
        }
        System.out.println("姓名" + '\t' + "语文" + '\t' + "数学" + '\t' + "英语" + '\t' + "总分");
        students.forEach(new Consumer<Student>() {
            @Override
            public void accept(Student student) {
                System.out.println(student);
            }
        });
    }
}

public class Student implements Comparable {
    private String name;
    private int chineseScore;
    private int mathScore;
    private int englishScore;
    private int zongfen;


    public Student() {
    }

    public Student(String name, int chineseScore, int mathScore, int englishScore, int zongfen) {
        this.name = name;
        this.chineseScore = chineseScore;
        this.mathScore = mathScore;
        this.englishScore = englishScore;
        this.zongfen = zongfen;
    }

    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 getZongfen() {
        return zongfen;
    }

    public void setZongfen(int zongfen) {
        this.zongfen = zongfen;
    }

    @Override
    public int compareTo(Object o) {
        Student student = (Student) o;
        //先根据总分排序
        int a = student.zongfen - this.zongfen;
        int b = (a == 0) ? student.chineseScore - this.chineseScore : a;
        int c = (b == 0) ? student.mathScore - this.mathScore : b;
        int d = (c == 0) ? student.englishScore - this.englishScore : c;
        int e = (d == 0) ? student.name.compareTo(this.name) : d;
        return e;
    }

    @Override
    public String toString() {
        return name + '\t' + chineseScore + '\t' + mathScore + '\t' + englishScore + '\t' + zongfen;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值