day15 Set集合

来源:互联网 发布:不用网络的三国游戏 编辑:程序博客网 时间:2024/06/05 05:22

对于Set集合来说,具体的类他是根据底层实现方式来构建的
List集合和Set集合的区别:
* Set:元素是唯一的,无序性(存储和取出不一致)
* List:元素可以重复,有序性(存储和取出一致)
一HashSet集合
1.1 如何不添加重复的元素
HashSet该集合包含的元素,必须重写HashCode()和equals()方法,(这些方法是在添加元素时候自动调用的)才可以保证元素的唯一不重复性,集合底层是用哈希表实现的,哈希表是一维数组,每个数组的元素又是由链表实现的,数组的下表是调用HashCode()方法得到的哈希值,在进行添加元素的时候,首先得到了元素的哈希值,根据哈希值确定数组的小标,然后调用equals()方法,比较内容是否相等,如果相等了,则元素重复。
注意: 自动生成的重写的方法 无法比较虽然内容一样,但是地址不一样的情况,所以要比较地址不一样,内容一样,就要改写equals()方法
提醒:字符串已经重写这两个方法
实例1:

Student类public class Student {private int age;private String name;public Student() {    super();    // TODO 自动生成的构造函数存根}public Student(int age, String name) {    super();    this.age = age;    this.name = name;}public int getAge() {    return age;}public void setAge(int age) {    this.age = age;}public String getName() {    return name;}public void setName(String name) {    this.name = name;}@Overridepublic String toString() {    return "Student [age=" + age + ", name=" + name + "]";}@Overridepublic int hashCode() {    final int prime = 31;    int result = 1;    result = prime * result + age;    result = prime * result + ((name == null) ? 0 : name.hashCode());    return result;}@Overridepublic boolean equals(Object obj) {    if (this == obj)        return true;    if(this!=obj)    if (obj == null)        return false;    if (getClass() != obj.getClass())        return false;    Student other = (Student) obj;    if (age != other.age)        return false;    if (name == null) {        if (other.name != null)            return false;    } else if (!name.equals(other.name))        return false;    return true;}}
public class HashSetDemo1 {    public static void main(String[] args) {        HashSet<Student> hs=new HashSet<Student>();        Student s1=new Student(20, "王帅");        Student s2=new Student(21, "王帅");        Student s3=new Student(20, "王帅");        Student s4=new Student(20, "张帅");        //只有Student同时重写了HashCode()方法和equals()才会在添加的时候过滤重复的元素         hs.add(s1);         hs.add(s2);         hs.add(s3);         hs.add(s4);         //如果Student 重写了hashCode()方法 只要内容一样,返回的值就一样,           //如果没有重写,地址不一样,就会返回不一样的hash值        for(Student s:hs)            System.out.println(s);//3个学生    }}

二TreeSet
1 如何实现元素的唯一:
TreeSet底层使用二叉树来实现的,在经行添加元素的时候,进行比较大小,但是如何经行比较大小呢,这时候就要用到比较器来进行比较
2 比较器 实现方式 one:
元素实现Comparable接口,然后重写compareTo()方法,自定义比较方法(如果想要全部添加元素,只需要在compareTo()方法里面返回一个非0数字即可 ,就可以重复添加元素

//实现接口public class Student2 implements Comparable<Student2>{private int age;private String name;public Student2() {    super();}public Student2(int age, String name) {    super();    this.age = age;    this.name = name;}public int getAge() {    return age;}public void setAge(int age) {    this.age = age;}@Overridepublic int compareTo(Student2 o) {    //重写的方法 如果年龄一样,就比较姓名的首字母顺序 字符串已经重写了compareto方法    int num1= this.age-o.age;    int num2=num1==0?this.name.compareTo(o.name):num1;    return num2;}@Overridepublic String toString() {    return "Student2 [age=" + age + ", name=" + name + "]";}}
public class demo1 {    public static void main(String[] args) {        // TODO 自动生成的方法存根      TreeSet<Student2> ts=new TreeSet<Student2>();      Student2 s1=new Student2(18,"wang");        Student2 s2=new Student2(17,"wang");        Student2 s3=new Student2(18,"zhao");        Student2 s4=new Student2(18,"li");        Student2 s5=new Student2(18,"wangg");        ts.add(s1);        ts.add(s2);        ts.add(s3);        ts.add(s4);        ts.add(s5);        for(Student2 s:ts)            System.out.println(s);    }}输出结果:Student2 [age=17, name=wang]Student2 [age=18, name=li]Student2 [age=18, name=wang]Student2 [age=18, name=wangg]Student2 [age=18, name=zhao]

比较器的实现方式two:
添加的元素类什么事情不用做,在实现创建集合类的时候去采用匿名内部类实现new Comparator比较方法
如: TreeSet st=new TreeSet(new Comparator() {

        @Override        //比较的方法体        }       }     );

需求:键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台

Student类  什么事情不用干public class Student { private String name; private int ChScore; private int EnScore; private int MaScore; private int CScore;public Student(String name, int chScore, int enScore, int maScore) {    super();    this.name = name;    ChScore = chScore;    EnScore = enScore;    MaScore = maScore;}public Student() {    super();    // TODO Auto-generated constructor stub}public String getName() {    return name;}public void setName(String name) {    this.name = name;}public int getChScore() {    return ChScore;}public void setChScore(int chScore) {    ChScore = chScore;}public int getEnScore() {    return EnScore;}public void setEnScore(int enScore) {    EnScore = enScore;}public int getMaScore() {    return MaScore;}public void setMaScore(int maScore) {    MaScore = maScore;}public int getCScore() {    CScore=this.ChScore+this.MaScore+this.EnScore;    return CScore;}@Overridepublic String toString() {    return "学生姓名:" + name +"\t"+ ", 语文成绩:" + ChScore +"\t"+ ", 英语成绩:"            + EnScore + "\t"+", 数学成绩:" + MaScore +"\t"+"总成绩为:"+CScore+"\t";}}
public class Demo1 {    public static void main(String[] args) {        //录入学生成绩        TreeSet<Student> ts=new TreeSet<Student>(new Comparator<Student>() {//采用了匿名内部类方法            public int compare(Student s1, Student s2) {                //实现比较方法                int num1=s1.getCScore()-s2.getCScore();                //如果总成绩一样,比较语文成绩                int num2=num1==0?s1.getChScore()-s2.getChScore():num1;                //如果语文成绩一样比较数学成绩                int num3=num2==0?s1.getMaScore()-s2.getMaScore():num2;                //如果数学成绩还一样 比较英语成绩                int num4=num3==0?s1.getEnScore()-s2.getEnScore():num3;                return num4;            }        });        //Scanner sc=new Scanner(System.in);        /*         * 本来是要输入3个学生的成绩,但是你只创建了一个键盘输入对象         * 所以 当你输入第二个学生信息时候,只会一直在录入第一个学生信息         */        for(int i=0;i<3;i++){            Scanner sc=new Scanner(System.in);//            Student ss=new Student();            String s=sc.nextLine();            int chScore=sc.nextInt();            int EnScore=sc.nextInt();            int MaScore=sc.nextInt();            ss.setName(s);            ss.setChScore(chScore);            ss.setEnScore(EnScore);            ss.setMaScore(MaScore);            ts.add(ss);        }        for(Student s:ts){            System.out.println();            System.out.println(s);        }    }}

比较器实现方法three
思想:单独写一个比较器然后实现Comparator接口
例子:

//MyComparatpr是Comparator接口的子实现类public class MyComparator implements Comparator<Student> {    @Override    public int compare(Student s1, Student s2) {//      return 0;//      按照学生姓名长度从小到大进行排序        //int num = this.name.lengt()-s.name.length();        //this--:s1        //s---: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 ;    }}
Student什么事情不用干public class Student {    private String name ;    private int age ;    public Student() {        super();    }    public Student(String name, int age) {        super();        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;    }}

随记:

1集合也重写了toString()方法,如果没有元素 输出[],
2 判断集合包含某元素contains(obj) 其实底层调用的是equals方法,所以判断包含的时候一定重写该方法
3不管是 TreeSet 还是HashSet 要想在内容一样的前提下,加入地址不一样的元素,都可以在equals()方法里面做文章

原创粉丝点击