day21--Java集合04

打印 上一主题 下一主题

主题 875|帖子 875|积分 2625

Java集合04

9.Set接口方法


  • Set接口基本介绍

    • 无序(添加和取出的顺序不一致),没有索引
    • 不允许重复元素,所以最多只有一个null
    • JDK API中接口的实现类有:

  • Set接口的常用方法:和List接口一样,Set接口也是Collection的子接口,因此,常用方法和Collection接口一样。
  • Set接口的遍历方式:同Collection的遍历方式一样,因为Set是Collection的子接口所以:

    • 可以使用迭代器
    • 增强for循环
    • 不能使用索引的方式来获取

例子1:以Set接口的实现类HashSet来讲解Set的方法
1.set接口的实现类的对象(set实现类对象),不能存放重复的数据,且最多只能添加一个null
2.set接口对象存放数据是无序的(即添加对象顺序和取出的对象顺序不一致)
3.注意:但是取出的顺序是固定的
  1. package li.collections.set;
  2. import java.util.HashSet;
  3. import java.util.Iterator;
  4. import java.util.Set;
  5. @SuppressWarnings("all")
  6. public class SetMethod {
  7.     public static void main(String[] args) {
  8.       
  9.         Set set = new HashSet();
  10.         set.add("john");
  11.         set.add("lucy");
  12.         set.add("john");
  13.         set.add("jack");
  14.         set.add("marry");
  15.         set.add(null);
  16.         set.add(null);
  17.         System.out.println(set);//取出的顺序是一致的:[null, marry, john, lucy, jack]
  18.         //遍历
  19.         //1.使用迭代器
  20.         Iterator iterator = set.iterator();
  21.         System.out.println("======迭代器遍历======");
  22.         while (iterator.hasNext()) {
  23.             Object obj =  iterator.next();
  24.             System.out.print(obj+"\t");
  25.         }
  26.         //2.增强for循环
  27.         System.out.println('\n'+"======增强for循环======");
  28.         for (Object o:set) {
  29.             System.out.print(o+"\t");
  30.         }
  31.         //set接口对象不能使用通过索引来获取,因此没有get方法
  32.         
  33.     }
  34. }
复制代码
10.HashSet


  • HashSet实现了接口Set
  • HashSet实际上是HashMap

  • 可以存放null值,但只能有一个null
  • HashSet 不保证元素是有序的,取决于hash后,再确定索引的结果
  • 不能有重复元素/对象
例子1:不允许重复元素
  1. package li.collections.set;
  2. import java.util.HashSet;
  3. import java.util.Set;
  4. @SuppressWarnings("all")
  5. public class HasSet_ {
  6.     public static void main(String[] args) {
  7.         Set hashSet = new HashSet();
  8.         //1.HashSet可以存放null,但是只能存放一个null,即不允许重复元素
  9.         hashSet.add(null);
  10.         hashSet.add(null);
  11.         System.out.println(hashSet);//[null]
  12.      }
  13. }
复制代码
例子2:
  1. package li.collections.set;
  2. import java.util.HashSet;
  3. @SuppressWarnings("all")
  4. public class HashSet01 {
  5.     public static void main(String[] args) {
  6.         HashSet hashSet = new HashSet();
  7.         //1.在执行add方法后会返回一个boolean值,添加成功返回true,失败则返回false
  8.         System.out.println(hashSet.add("john"));//true
  9.         System.out.println(hashSet.add("lucy"));//true
  10.         System.out.println(hashSet.add("john"));//false,可以看出这里添加失败了,不允许重复元素
  11.         System.out.println(hashSet.add("jack"));//true
  12.         System.out.println(hashSet.add("rose"));//true
  13.         //2.可以通过remove()指定删除哪个对象
  14.         hashSet.remove("john");
  15.         System.out.println(hashSet);//[rose, lucy, jack]
  16.     }
  17. }
复制代码
10.1怎么理解不能添加相同的元素/数据?

例子:
  1. package li.collections.set;
  2. import java.util.HashSet;
  3. @SuppressWarnings("all")
  4. public class HashSet01 {
  5.     public static void main(String[] args) {
  6.         HashSet hashSet = new HashSet();
  7.         hashSet.add("lucy");//添加成功
  8.         hashSet.add("lucy");//添加失败
  9.         hashSet.add("lucy");//添加失败
  10.         hashSet.add(new Dog("tom"));//添加成功
  11.         hashSet.add(new Dog("tom"));//添加成功
  12.         System.out.println(hashSet);//[Dog{name='tom'}, Dog{name='tom'}, lucy]
  13.         //!!!经典面试题:
  14.         hashSet.add(new String("jackcheng"));//添加成功
  15.         hashSet.add(new String("jackcheng"));//添加失败,为什么呢?
  16.         System.out.println(hashSet);//[jackcheng, Dog{name='tom'}, Dog{name='tom'}, lucy]
  17.     }
  18. }
  19. class Dog{
  20.     private String name;
  21.     public Dog(String name) {
  22.         this.name = name;
  23.     }
  24.     @Override
  25.     public String toString() {
  26.         return "Dog{" +
  27.                 "name='" + name + '\'' +
  28.                 '}';
  29.     }
  30. }
复制代码
为什么相同的两个 hashSet.add(new Dog("tom")); hashSet.add(new Dog("tom"));语句可以添加成功,而却添加失败呢?原因在于HashSet的底层机制
  1.     hashSet.add(new String("jackcheng"));//添加成功
  2.     hashSet.add(new String("jackcheng"));//添加失败,为什么呢?
复制代码
10.2HashSet的底层扩容机制

HashSet底层是HashMap,HashMap底层是数组+链表+红黑树
说明:

  • HashSet底层是HashMap第一次添加时,table数组扩容到16,临界值(threshold)是16*加载因子(loadFactor,0.75)=12;如果table数组容量使用到了临界值12,就会扩容到16 * 2=32,新的临界值就是32 * 0 .75=24,依此类推(两倍扩容)
注意:这里的容量计算的不仅仅是table数组上的容量,链表上的容量也算。即只要增加了一个元素,使用的容量就+1
例如:当一个table表的数组某个索引位置上存储了一个值,而这个值后面的链表存储了7个值,加起来就是8,那么在数组长度没有超过64时,再加入一个值,数组就会进行两倍扩容

  • 添加一个元素时,先得到一个hash值--会转成--索引值
  • 找到存储数据表table,看这个索引位置是否已经存放有元素
    3.1 如果没有则直接加入
    3.2 如果有,则调用equals()比较,如果相同就放弃添加;如果不相同则添加到最后
  • 在jdk8中,如果一条链表的元素个数 >= TREEIFY_THRESHOLD (默认为8),并且table数组的大小 >= MIN_TREEIFY_CAPACITY (默认为64)就会进行树化(红黑树),否则仍然采用数组扩容机制
例子:模拟链表
  1. package li.collections.set;
  2. public class HashSetStructure {
  3.     public static void main(String[] args) {
  4.         //模拟一个HashSet的底层(即HashMap的底层结构)
  5.         //1.创建一个数组,数组的类型是Node
  6.         Node[] table = new Node[16];
  7.         System.out.println(table);
  8.         //2.创建结点
  9.         Node john = new Node("john", null);
  10.         table[2] = john;
  11.         Node jack = new Node("jack", null);
  12.         john.next = jack;//将Jack结点挂载到john后面
  13.         Node rose = new Node("rose", null);
  14.         jack.next = rose;//将rose结点挂载到jack后面
  15.         Node lucy = new Node("lucy", null);
  16.         table[3] = lucy;//把lucy存放到table表索引为3 的位置
  17.         System.out.println(table);
  18.     }
  19. }
  20. class Node {//结点,用于存放数组,可以指向下一个节点从而形成链表
  21.     Object item;//存放数据
  22.     Node next;//指向下一个节点
  23.     public Node(Object item, Node next) {
  24.         this.item = item;
  25.         this.next = next;
  26.     }
  27. }
复制代码
例子2:HashSet的两倍扩容机制

  • 如图,HashSet第一次添加数据,table数组的长度为16

  • 在数组容量使用到12(临界值) 时,会进行一个两倍的扩容(12*0.75=32)

例子3:HashSet的树化
  1. package li.collections.set.hashset;
  2. import java.util.HashSet;
  3. @SuppressWarnings("all")
  4. public class HashSetSource {
  5.     public static void main(String[] args) {
  6.         HashSet hashSet = new HashSet();
  7.         for (int i = 1; i <=12 ; i++) {
  8.             hashSet.add(new A(i));
  9.         }
  10.         
  11.         System.out.println(hashSet);
  12.     }
  13. }
  14. class A {
  15.     private int n;
  16.     public A(int n) {
  17.         this.n = n;
  18.     }
  19.     @Override
  20.     public int hashCode(){//重写hashCode方法
  21.         return 100;
  22.     }
  23. }
复制代码
</ol>
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

农妇山泉一亩田

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表