天天看点

JavaSE基础自学------集合框架--Set体系

Set

    • Set体系
    • HashSet
    • TreeSet-------

Set体系

Set : 元素是无序的(存入和取出的顺序不一定一致),元素不可以重复

Set集合的功能和Collection 是一致的

Set体系常用集合容器(HashSet / TreeSet)

  • HashSet : 底层数据结构是哈希表
  • TreeSet : 底层数据结构是二叉树,可以对Set集合中的元素进行排序

HashSet

HashSet 是如何保证元素的唯一性?

是通过两个方法: hashCode 和equals 来完成

每个元素都有自身的哈希值, 而HashSet底层是哈希表, 用来存放哈希值的

如果元素的HashCode值相同, 才会判断equals是否为true

如果元素的HashCode值不相同,则不会调用equals

.

1,hashCode获取元素哈希值

2,判断集合内是否有与之相同的哈希值,如果有,则调用equals判断元素是否相同,如果没有则存入集合中

!注:对于判断元素是否存在,以及删除等操作,依赖的方法也是元素的hashCode 和equals

一般的,hashCode 和equals 方法都要根据实际需求,实际判断条件来重写

代码演示------

本例中,如果按照默认hashCode 方法来new对象,则每个对象的哈希值都是不同的,但是对象的条件可能是相同的

所以根据条件可以自定义哈希值,

import java.util.*;  //导入集合类包
//自定义人对象,对象添加到hashSet集合中,同名同年龄为重复元素
class Person {
    private String name;
    private int age;

    public int hashCode() {
        System.out.println(name + " hashCode " + name.hashCode());
        return name.hashCode() + age * 29;    //根据实际条件可以自定义哈希值,保证了哈希值的唯一性,减少调用equals
    }

    public boolean equals(Object obj) {  //重写equals定义判断条件

        if (!(obj instanceof Person)) {  //判断输入元素是否为Person,否则返回false
            return false;
        }
        Person p = (Person) obj;        //多态.向下转型才能调用子类成员

        System.out.println(this.name + "   equals  " + p.name);   //参考,,哪段代码调用了equals

        return this.name.equals(p.name) && this.age == p.age;  //定义判断条件:名字,年龄相同就返回true
    }

    Person(String name, int age) {
        this.age = age;
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

public class DEMO {
    public static void main(String[] args) {
        HashSet hs = new HashSet();
        hs.add(new Person("java1", 10));
        hs.add(new Person("java2", 12));
        hs.add(new Person("java1", 10));
        hs.add(new Person("java3", 13));
        hs.add(new Person("java3", 13));
        System.out.println("------------------------");

        sop("是否包含 " + hs.contains(new Person("java1", 10)));

        System.out.println("------------------------");
        
        Iterator it = hs.iterator();       //对集合进行迭代
        while (it.hasNext()) {
            Person p = (Person) it.next();
            System.out.println(p.getName() + "   " + p.getAge());
        }
    }
           
JavaSE基础自学------集合框架--Set体系

TreeSet-------

TreeSet :底层数据结构是二叉树, 可以对Set集合中的元素进行排序

保证唯一性的依据是:int compareTo return 0;

TreeSet排序的第一种方式----- Comparable

让元素自身具备比较性,元素需要实现Comparable接口,覆盖comparaTo方法,这种方式称为元素的自然排序

int compareTo(T o) -----比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。

TreeSet排序的第二种方式----- Comparator(比较器)

当元素内部不具备比较性,或者元素具备的比较性不是所需要的

那这时可以可以定义一个 Comparator(比较器)类,在比较器内重写conpare方法定义比较条件

int compare(T o1,T o2) ------ 比较用来排序的两个参数。根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数。

注:java很多类中已经定义了Comparable,如 String类,Integer类

注:当元素中具备Comparable,又定义了Comparator…最终是调用Comparator来对元素进行排序

Comparable 与 Comparator(比较器) 区别

  • Comparable可以认为是一个内比较器…Comparator可以认为是是一个外比较器
  • 如果实现类没有实现Comparable接口,又想对两个类进行比较(或者实现类实现了Comparable接口,但是对compareTo方法内的比较算法不满意),那么可以实现Comparator接口,自定义一个比较器,写比较算法

Comparable 代码演示-----

将学生对象存入 TreeSet中

根据年龄为主要条件进行排序,姓名为次要条件

当主条件相同时,判断次要条件

import java.util.*;  //导入集合类包
class Student implements Comparable{  //继承Comparable 让学生具备比较性
    private String name;
    private int age;
    
    Student(String name, int age){
        this.name=name;
        this.age=age;
    }
    public int compareTo(Object obj){      //重写conpareTo方法,重新定义年龄为主要比较条件,姓名为次要条件
        if (!(obj instanceof Student)){    //如果对象不是学生,则抛出异常
            throw  new  RuntimeException("不是学生对象");
        }
        Student s=(Student)obj;   //向下转型

        System.out.println(this.name+"  conpar  "+s.name);  //参考代码调用该方法
        if (this.age>s.age)
            return 1;
        if (this.age==s.age){
            return this.name.compareTo(s.name);  //当年龄相同时,则判断次要条件:姓名,
        }                                       //因为String类中已经定义了比较comparable,所以可以直接调用conpareTo
        return -1;
    }

    public String getName(){
        return name;
    }
    public int getAge(){
        return age;
    }
}

public class DEMO {

    public static void main(String[] args) {
        TreeSet ts = new TreeSet();

        ts.add(new Student("java1",10));
        ts.add(new Student("java3",13));
        ts.add(new Student("java2",13));
        ts.add(new Student("java2",13));

        System.out.println("--------------------");
        Iterator it=ts.iterator();

        while (it.hasNext()){

            Student s=(Student)it.next();
            System.out.println(s.getName()+"    "+s.getAge());
        }
    }
}
           
JavaSE基础自学------集合框架--Set体系

Comparator 代码演示------

将学生对象存入 TreeSet中,定义一个比较器类,并使用该比较器

根据姓名为主要条件进行排序,年龄为次要条件

当主条件相同时,判断次要条件

import java.util.*;  //导入集合类包

class Student{  
    private String name;
    private int age;

    Student(String name, int age){
        this.name=name;
        this.age=age;
    }
    public String getName(){
        return name;
    }
    public int getAge(){
        return age;
    }
}

class MyCompare implements Comparator{   //定义比较器,实现Comparator接口
    public int compare(Object o1,Object o2){  //重写conpare方法

        Student s1=(Student)o1;
        Student s2=(Student)o2;

      int num=  s1.getName().compareTo(s2.getName());  //比较姓名

      if (num==0){
          return new Integer(s1.getAge()).compareTo(s2.getAge()); //当姓名相同时,比较年龄
      }
        return num ;
    }
}

public class DEMO {

    public static void main(String[] args) {
        TreeSet ts = new TreeSet(new MyCompare());  //调用比较器
        ts.add(new Student("java3",16));
        ts.add(new Student("java1",13));
        ts.add(new Student("java2",10));
        ts.add(new Student("java7",10));
        ts.add(new Student("java7",9));
        
        Iterator it=ts.iterator();
        while (it.hasNext()){

            Student s=(Student)it.next();
            System.out.println(s.getName()+"    "+s.getAge());
        }
    }
}
           
JavaSE基础自学------集合框架--Set体系

TreeSet练习-------

练习:按照字符串的长度排序,相同长度则按自然排序

字符串本身具备了比较性(Comparable),但是它的比较性不是我们所需的

这时则需要定义比较器(Comparator),

import java.util.*;  //导入集合类包
class MyCompare implements Comparator{   //定义比较器,实现Comparator接口
    public int compare(Object o1,Object o2) {  //重写conpare方法

        String s1=(String)o1;
        String s2=(String)o2;

        //int num =new Integer(s1.length()).compareTo(s2.length()); 这种写法更简便

        if (s1.length()>s2.length()){
            return 1;
        }else if (s1.length()==s2.length()){
            return s1.compareTo(s2);   //长度相同则进行自然排序比较
        }return -1;
    }
}

public class DEMO {

    public static void main(String[] args) {
        TreeSet ts = new TreeSet(new MyCompare());  //调用比较器
        ts.add("caaddd");
        ts.add("z");
        ts.add("abc");
        ts.add("aaa");
        ts.add("yacccdsad");
        
        Iterator it=ts.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }
    }
}
           
JavaSE基础自学------集合框架--Set体系