Java基础第十三天--Set, HashSet, TreeSet

来源:互联网 发布:街霸5 网络 编辑:程序博客网 时间:2024/04/29 16:50

1.  Stack栈:它的父类是Vector  扩展了5个方法
 

1)添加功能:public Object push(Object obj) --添加元素并把元素本身返回
2)获取功能:peek() 只查看,不移除 
      pop() 查看并移除  --移除栈顶元素并返回该元素
3)boolean empty()   --测试堆栈是否为空
 
2. 接口set :特点,唯一性,无序(存入和取出顺序不一致)
 相对于其父类Collection,Set没有特别的方法要学习
 
3. HashSet集合是怎么保证元素的唯一性的?

HashSet集合底层数据结构是哈希表 --基于hashmap
 

需求:存储自定义对象,并去掉重复值(当两个对象的成员值都相同)
  a)按照正常做法,发现并没有去掉重复值
  b)我们查看原码,发现是add()方法中进行的重复值的判断
    e.hash == hash && ((k=e.key)==key || key.equals(k))
    注意:hash是和hashCode()方法相关的
   
    这个判断有两个条件:
    1)e.hash == hash  依赖hashCode()方法进行比较
    2)((k=e.key)==key || key.equals(k)) 
 
 哈希表底层依赖于两个方法:hashCode()和equals()方法
 先执行hashCode()值的比较:
 相同:继续走equals()方法比较成员的值
        返回True:对象的成员值相同,那么就是同一个对象,不存储到集合中
        返回False:对象的成员值不同,就添加到hashset集合中
 不同:直接添加到集合中
  

 以后如果涉及到Hash这种数据结构,要明白可能需要重写两个方法
         HashCode() --重写它是为了保证能走equals(),优化它,是为了提高效率
         Equals() -- 是为了比较成员的内容
  如果不知道怎么写,那么可以source--自动生成
  
 案例:  HashSet存储字符串并遍历(String类重写了hashCode()和equals()方法)
            HashSet存储自定义对象并遍历(在自定义类中source--create hashCode() and equals()

4. LinkedHashSet 是HashSet的子类
 底层数据结构是哈希表和链表两种,所以有序,唯一
 
5. TreeSet--底层基于TreeMap(二叉树)
 可以自然排序,或者比较器排序(创建set时提供的Comparator)
 具体排序情况,参照构造方法


 1)无参构造 TreeSet()--自然排序
 

案例:TreeSet存储多个自定义对象并遍历
需求:存储多个学生对象,并按照学生的年龄从小到大排序
  如果两个对象的内容都相同,我们就认为对象是重复的
  a)按正常做法,报错
  java.lang.ClassCastException: Student cannot be cast to java.lang.Comparable
  这个错误表明是类型转换问题
  因为TreeSet使用的是自然排序规则,而你并没有实现自然排序接口Comparable
  这个接口是哪个对象要排序,就应该被该对象所属的类来实现


  b)Student implemments Comparable接口并重写其Compare to()方法 发现
  如果返回值是0,说明元素重复,只存储第一个
  如果返回值大于0,正向存储
  如果返回值小于0,逆向存储


  c)重写CompareTo()方法,要分析出排序的主要条件和次要条件
  基本类型,直接用减法;引用类型,使用String类的compareTo()方法
   // 主要条件 -- 年龄
   // 次要条件 -- 姓名  
   int num = this.age-o.age;  
   return num==0?this.name.compareTo(o.name):num;


  总结:

  TreeSet如何保证元素的唯一性 -- 根据返回值是否为0
  TreeSet如何保证元素的排序 -- 根据元素所属的类实现自然排序接口Comparable,
  然后按照你的排序规则进行比较
   
 2)带参构造 TreeSet(Comparator<? super E> comparator)  <? super E> 泛型限定

  构造一个空的TreeSet,它根据指定比较器进行排序
  a)创建TreeSet集合的时候,传递comparator接口的子类对象
   Comparator<Student> myComparator = new MyComparator();
   TreeSet<Student> ts = new TreeSet<Student>(myComparator);
  b)在实现Comparator接口的自定义类中重写compare()方法
   public int compare(Student s1, Student s2){}
    
 自然排序--元素具备比较性
         被装载对象所属的类实现Comparable接口
 比较器排序--集合具备比较性
         创建TreeSet集合的时候,传递Comparator接口的子类对象
  
 一个重点知识:
 如果一个方法的参数是接口或者抽象类的时候,在只调用一次的情况下,我们可以使用匿名内部类来实现

   TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {   @Override   public int compare(Student s1, Student s2) {    int num = s1.getAge() - s2.getAge();    return num == 0 ? s1.getName().compareTo(s2.getName()) : num;   }  }); 

 案例:

TreeSet存储字符串并遍历(String类已经实现了Comparable接口)
TreeSet存储Integer并遍历(Integer类也已经实现了Comparable接口)
TreeSet存储自定义对象并遍历(三种方法:

1. 无参构造+自定义对象类实现Comparable接口;

2. 有参构造+显式定义Comparator接口;

3. 有参构造+Comparator的匿名内部类)

0 0
原创粉丝点击