A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© yijincheng 中级黑马   /  2016-3-22 21:15  /  778 人查看  /  1 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 yijincheng 于 2016-3-22 22:27 编辑

今天的学习内容是集合的Set结构
相比于Link结构,Set的特点是无序(存储和读取的顺序是不一致的) ,无索引,不可以重复存储相同元素。
Ste集合的这个帮派中,有HashSet和TreeSet两大马仔。两个各司其职,各有擅长的地方。

类 hashSet <.E>
        这个类的特点是:
不保证迭代顺序;
也不保证顺序不变(上次输出结果和下次输出结果未必一样,即使没有对容器进行任何操作和修改);
但是能够保证元素不重复。(这恐怕就是hashSet的看家本领了)

hashSet这个唯一赖以生存的本领的实现原理是什么呢?
首先就是写在的名字上的hash。
1.HashSet原理
        * 我们使用Set集合都是需要去掉重复元素的, 如果在存储的时候逐个equals()比较, 效率较低,哈希算法提高了去重复的效率, 降低了使用equals()方法的次数
        * 当HashSet调用add()方法存储对象的时候, 先调用对象的hashCode()方法得到一个哈希值, 然后在集合中查找是否有哈希值相同的对象
                * 如果没有哈希值相同的对象就直接存入集合
                * 如果有哈希值相同的对象, 就和哈希值相同的对象逐个进行equals()比较,比较结果为false就存入, true则不存
2.将自定义类的对象存入HashSet去重复
         类中必须重写hashCode()和equals()方法
        
hashCode(): 属性相同的对象返回值必须相同, 属性不同的返回值尽量不同(提高效率)
         equals(): 属性相同返回true, 属性不同返
在向集合中添加元素时,内在的逻辑是先比较元素的hashCode,当hashCode一样时,再用equals方法比较。
Hashcode是方法hashCode()生成的很有可能是元素独有的标识。
  1. @Override
  2.         public int hashCode() {
  3.                 final int prime = 31;
  4.                 int result = 1;
  5.                 result = prime * result + age;
  6.                 result = prime * result
  7.                                 + ((name == null) ? 0 : name.hashCode());
  8.                 return result;
  9.         }
  10. PS:这里的prime的值为何是31?一方面是因为它是个不大不小的质数,这样算出来的hashCode更容易独一无二。另一方面,31是2^5-1,系统得到这个数比较快。
  11.         @Override
  12.         public boolean equals(Object obj) {
  13.                 if (this == obj)
  14.                         return true;
  15.                 if (obj == null)
  16.                         return false;
  17.                 if (getClass() != obj.getClass())
  18.                         return false;
  19.                 Person other = (Person) obj;
  20.                 if (age != other.age)
  21.                         return false;
  22.                 if (name == null) {
  23.                         if (other.name != null)
  24.                                 return false;
  25.                 } else if (!name.equals(other.name))
  26.                         return false;
  27.                 return true;
  28.         }
复制代码


Tips:eclipse中,在自定义类中,shift + Alt + s 再按h ,可以自动生成hashCode和equals方法
LinkedHashSet
特点: 可以保证怎么存就怎么取
在操作上,LinkedHashSet没什么特殊之处。和其他集合的操作相同。

TreeSet
        首先,TreeSet是一个用来对元素排序的的集合。这个功能很强大,以后就不用自己写那麻烦的双循环嵌套的排序算法了。
自定义类必须实现Comparable接口,才能成功被添加进TreeSet集合中。
实现Comparable接口就要重写CompareTo方法。当对象被添加进集合中时,集合会调用该对象的CompareTo方法和集合内的元素进行比较。
CompateTo 会返回一个int类型。
TreeSet的数据结构是二叉树。每个节点都有两个引用,分别指向下一级的左节点、右节点。
CompareTo的返回值是负数时,新元素存数在左边;是正数时,存放在右边;等于0时不存储。
读取的顺序是左中右。这样就实现了对元素的排序。

当然,自定义类的CompareTo你也可以重写,按实际要求做出修改。例如当要求允许重复元素时,就要把返回值0的情况归到不为零的判断中。

TreeSet的比较器排序。
        比较器需要自己定义。因为只是在实例化TreeSet时才调用一次比较器,所以可以用匿名内部类的方式来定义。
例如:
  1. TreeSet<String> ts = new TreeSet<>(new Comparator<String>() {//定义比较器(new Comparator(){}是Comparator的子类对象)
  2.                
  3.                         @Override
  4.                         public int compare(String s1, String s2) {                                //重写compare方法
  5.                                 int num = s1.compareTo(s2);                                        //比较内容
  6.                                 return num == 0 ? 1 : num;                                                //如果内容一样返回一个不为0的数字即可
  7.                         }
  8. });
复制代码

两种排序方式的总结:
        * a.自然顺序(Comparable)
                * TreeSet类的add()方法中会把存入的对象提升为Comparable类型
                * 调用对象的compareTo()方法和集合中的对象比较
                * 根据compareTo()方法返回的结果进行存储
        * b.比较器顺序(Comparator)
                * 创建TreeSet的时候可以制定 一个Comparator
                * 如果传入了Comparator的子类对象, 那么TreeSet就会按照比较器中的顺序排序
                * add()方法内部会自动调用Comparator接口中compare()方法排序
                * 调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数
        * c.两种方式的区别
                * TreeSet构造函数什么都不传, 默认按照类中Comparable的顺序(没有就报错ClassCastException)
                * TreeSet如果传入Comparator, 就优先按照Comparator

1 个回复

倒序浏览
很好,也可以考下来看看
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马