黑马程序员 Set集合和泛型

------- android培训java培训、期待与您交流! -------------------------------- 

1. Set集合
  不允许存储重复元素,没有下标,无序集合,存储的顺序和取出的顺序不一定一致
  Set接口中的方法,和Collection中的方法一致的
Set接口的实现类有HashSet,LinkedHashSet和TreeSet
2. HashSet集合
   a. 底层是哈希表结构
   b.线程不安全
   c.允许存储null
   d.无序,不重复

   注意:
    为什么存储自定义对象,重写了equals没有效果
    HashSet底层的哈希表的原理,如何去掉重复对象呢
   下面我们慢慢解释
  哈希值:
    每一个对象,都有自己的哈希值
    哈希值是一个对象建立后,JVM根据哈希算法,计算出来的一个十进制数
    这个十进制数就是哈希值
    Person@123EA21
    123EA21 哈希值,哈希值不是地址值
    在Object类中,有一个方法hashCode()计算哈希值的,本地方法
    程序演示哈希值
    结论,HashSet集合,存储对象的时候
    依据是对象的哈希值码,如果对象的哈希值一致,再次比较equals
    返回真,同一个对象,不存储
    返回假,后进来的对象,像笼屉一样,挂靠在上一个对象的下面

    哈希值,存储的是哈希值,桶状结构
    当将对象存储到HashSet集合的时候,集合首先会调用对象的hashCode方法,获取哈希值
    如果两个对象的哈希值一致,再次调用equals方法


   自定义定的对象,有肯能被存储到HashSet集合,必须重写hashCode equals方法


 3. 两个对象
   如果哈希值相同 equals 一定返回真吗  No
   如果equals返回真,两个对象一定具有相同的哈希值吗  YES


 4. TreeSet 集合
    4.1  TreeSet集合,对存储到的对象进行排序,因此必须保证存储的对象具有比较性
     在TreeSet集合中,存储自定义对象的时候,抛出类型转换异常
       Person不能被转换成java.lang.Comparable


   4.2  此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序
      实现这个接口的累,进行整体排序,自然顺序


   4.3  TreeSet集合,需要对存储的对象进行排序,TreeSet集合排序的依据是什么?
      依据的是对象的自然顺序,凡是实现了Comparable接口的,都叫做自然顺序

      Person类,没有实现Comparable接口,不具备自然顺序
          JDK1.7,1.5版本,TreeSet存储一个对象,出现异常,对象没有自然顺序
          JDK1.6版本,存储一个对象,不会出现异常,存储一个以上的时候,出现异常

   4.4  如果存储的是String类对象,被TreeSet排序了,并且没有异常
      是因为String类实现了Comparable接口

    String类,比较自然顺序的方法compareTo
     s1.compareTo(s2)
      如果s1 比 s2 小  小于0
    如果s1 比 s2 大  大于0
        如果s1 和s2一样  返回0
  
        存储字符串的时候,TreeSet集合,会调用String类中的compareTo方法,实现排序

        TreeSet(Comparator comparator) 
        构造一个新的空 TreeSet,它根据指定比较器进行排序。


  TreeSet集合,构造方法中,传递一个参数,Comparator类型
  Comparator是一个比较器,用来比较对象的

  java.lang.Comparable 实现接口,类具备了自然顺序
  java.util.Comparator 比较器,比较器优先


  定义类,实现Comparator接口
  建立TreeSet对象的时候,在构造方法中,传递接口的实现类对象
  TreeSet集合,就会安照自定义的比较器进行排序了


  4.5 定义比较器三步骤
        定义类,实现java.util.Comparator接口
        重写compare方法
        建立TreeSet集合,传递比较器对象


 5. TreeSet集合案例
   集合中存储String对象,按照长度排序,如果长度一致,按照字典顺序排序
   String类,自己具备自然顺序,实现长度排序,自己写比较器
/**
 * 10、声明类Student,包含3个成员变量:name、age、score, 创建5个对象装入TreeSet,按照成绩排序输出结果(考虑成绩相同的问题)。
 */
/*
 * 分析:只要按着题目要求一步一步做就可以了 其中需要注意的是:Student类在实现自身比较性的时候需要考虑泛型,即安全性 排列顺序按着成绩从高到低排列
 */

import java.util.*;
public class Test10 {
public static void main(String[] args) {
// 创建TreeSet对象 scoreForm 成绩表
TreeSet<Student> scoreForm = new TreeSet<>();
// 创建5个对象装入TreeSet(考虑成绩相同的问题)


scoreForm.add(new Student("赵小刚", 20, 88));
scoreForm.add(new Student("钱小明", 19, 92));
scoreForm.add(new Student("孙小强", 17, 95));
scoreForm.add(new Student("李小龙", 18, 92));
scoreForm.add(new Student("周小花", 16, 97));
//调用方法,按照成绩排序输出
form(scoreForm);
}
//定义方法,迭代输出
private static void form(TreeSet<Student> scoreForm) {
// Iterator接口,迭代器,对 collection 进行迭代的迭代器
Iterator<Student> it = scoreForm.iterator();
// 循环输出,hasNext()如果仍有元素可以迭代,则返回 true
while (it.hasNext()) {
// next() 返回迭代的下一个元素。
Student student = it.next();
System.out.println("姓名:" + student.getName() + ",年龄:"
+ student.getAge() + ",成绩:" + student.getScore());
}
}
}


// 因为往TreeSet集合中存元素,TreeSet具有排序功能,但是需要元素自身具有比较性
// 元素需要实现Comparable接口,覆盖CompareTo方法
// 声明类Student
class Student implements Comparable<Student> {
private String name;
private int age;
private int score;
// 构造函数,方便赋值
Student(String name, int age, int score) {
this.name = name;
this.age = age;
this.score = score;
}
// 覆盖compareTo方法
public int compareTo(Student student) {
// score 是基本数据类型可以直接运算,this.score-student.score用num记录,num不等于0,就直接返回num
// 如果num等于零,即this.score==student.score,再比较其他的成员变量
int num = this.score - student.score;
if (num == 0)
return this.name.compareTo(student.name);
else
// 如果直接返回num,就会按照数字的自然顺序排列,即从大到小排,不符合常规,那我们就返回-num
return -num;
}
// 提供set和get方法
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;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}
 6. LinkedHashSet
    有序的Set集合,怎么存储怎么取出


 7. JDK1.5版本新特性 -- 泛型 Generic
     泛型是一种安全机制
   7.1 怎么使用泛型,格式定义
     集合类<数据类型> 变量 = new 集合类<数据类型>();
     指示这个集合,只能存储已经定义的数据类型

   7.2程序的安全问题,由原理的运行时期,提起到了编译时期,很重要
   好处: 避免了数据类型的强制转换

      代码量减少了
        写集合,要求使用泛型实现
 
   7.3什么使用使用泛型呢?
     a.当你用一个类的时候,发现这个类的右边有<>
     b.ArrayList<String>
     c.ArrayList<String>  E 就是一个变量而已
     d.boolean add(String e) 
    

8. 自定义泛型,提高安全性(了解)
  写一个案例,体现安全性
  写一个造对象的工厂,造什么对象不清楚
  利用泛型,提高程序的安全性,不可以随便传递参数

9. 泛型的类,泛型的方法(了解)
  泛型类,在定义类的时候,在类的右边写<变量>
  泛型方法,是在方法的声明上写<变量>
10. 泛型接口
  在接口上定义泛型
  接口是需要类实现
    类实现接口,不指定泛型,由创建实现类的同时指定类型
    类实现接口,直接指定泛型
11. 泛型的通配符
  泛型的通配符<?>表示不清楚泛型是什么数据类型
  如果只简单的做遍历迭代是可以的,提高安全性,避免强制转换不可以了

ASP.Net+Unity开发.Net培训、期待与您交流! ---------------------- 详细请查看:www.itheima.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值