Java集合框架(三)-----Set接口

Collection接口之二(Set接口):

一、Set:存储无序,不可重复的集合,底层为链表

Set接口的实现类:

在这里插入图片描述
1、HashSet:作为set接口的主要实现类,线程不安全,可以存储null值
2、 LinkedHashSet:作为HashSet的子类,遍历其内部数据时,可以按照添加的顺序遍历,对于频繁的遍历操作,效率高
3、 TreeSet:可以按照添加对象的指定属性,进行排序

总结

1.Set接口中没有额外定义方法,都是使用的Collection中声明过的方法。
2.要求1:想Set中添加的数据,其所在的类一定要重写hashCode()和equals()–>一般使用快捷方式生成
要求2:重写的hashCode()和equals()尽可能保持一致性:相等的对象必须具有相同的哈希值
1)对于==,如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;
如果作用于引用类型的变量,则比较的是所指向的对象的地址
2)对于equals方法,注意:equals方法不能作用于基本数据类型的变量
如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;
诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。

二、Set的实现过程

Set:存储无序,不可重复的集合(HashSet)
1.无序性:不等于随机性。
存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值来决定的。

2.不可重复性:保证添加的元素按照equals()判断时,不能返回true。即:相同元素只能有一个。
3.添加元素的过程:以HashSet为例 底层:数组+链表(jdk7)
我们向HashSet中添加元素a,首先调用元素a所在类的HashCode()的方法,计算元素a的哈希值,
此哈希值接着通过某种算法计算出HashSet底层的数组存放位置(即为:索引位置),判断
数组此位置上是否有元素:
如果此位置上没有元素,则a添加成功。—>情况一
如果此位置上有其他元素b(或以链表形式存在多个元素),则比较元素a和元素b的哈希值:
如果哈希值不同,则元素a添加成功 —>情况二
如果哈希值相同,进而调用元素a所在类的equals()方法
equals()返回true,则元素a添加失败。
equals()返回false,则元素a添加成功。—>情况三
对于添加成功的情况二和情况三而言:元素a已经存在指定索引位置上的数据以链表的形式存储
jdk 7:元素a放到数组中,指向原来的元素(头部插入)
jdk 8:原来的元素在数组中,指向元素a(尾部追加)
总结:七上八下

在这里插入图片描述

   @Test
    public void  test(){
        Set set = new HashSet();
        set.add(123);
        set.add(123);
        set.add(456);
        set.add("AA");
        set.add("AA");
        set.add("BB");
        set.add(new Person("Tom",22));
        set.add(false);

        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
            System.out.print(iterator.next() +"\t");
            //AA	BB	Person{name='Tom', age=22}	false	456	123
        }

三、 LinkedHashSet的使用

LinkedHashSet作为HashSet的子类,在添加数据的同时,还维护了两个引用,记录前一个数据和后一个数据

优点:对于频繁的遍历操作,效率高

    @Test
  public void  test1(){
      Set set = new LinkedHashSet();
      set.add(123);
      set.add(123);
      set.add(456);
      set.add("AA");
      set.add("AA");
      set.add("BB");
      set.add(new Person("Tom",22));
      set.add(false);

      Iterator iterator = set.iterator();
      while(iterator.hasNext()){
          System.out.print(iterator.next() +"\t");
         //123	456	AA	BB	Person{name='Tom', age=22}	false
      }
  }

四、 TreeSet的使用

在这里插入图片描述
1.向TreeSet中添加的数据,要求是相同类的对象
2.两种排序方式:自然排序(在使用类中实现Comparable接口重写compareTo方法) 和 定制排序
3.自然排序: 比较两个对象是否相同的标准为:compareTo()返回0,不在是equals()

  @Test
    public void  test3(){
        TreeSet set = new TreeSet();

        //错误
//        set.add(123);
//        set.add(123);
//        set.add(456);
//        set.add("AA");
//        set.add("AA");
//        set.add("BB");
//        set.add(new Person("Tom",22));
//        set.add(false);
        //一
//        set.add(133);
//        set.add(456);
//        set.add(-145);
//        set.add(12);
//        set.add(6);
        //二
        //  //详细可见Java集合框架(一)-----Collection接口中的Person类
        set.add(new Person("Tom",23));
        set.add(new Person("FAS",15));
        set.add(new Person("SDF",45));
        set.add(new Person("WER",32));
        set.add(new Person("AF",20));
        //如果compareTo没有重写年龄的话,就只会有一个对象
        set.add(new Person("AF",50));

        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
            System.out.print(iterator.next() +"\t");
        }
    }

4.TreeSet的定制排序
比较两个对象是否相同的标准为:Comparator的compare()返回0,不在是equals()

 @Test
   public void  test4() {
       Comparator com = new Comparator() {
           //按照年龄从小到大排列
           @Override
           public int compare(Object o1, Object o2) {
               if (o1 instanceof Person && o2 instanceof Person){
                   Person p1 = (Person)o1;
                   Person p2 = (Person)o2;
                   return Integer.compare(p1.getAge(),((Person) o2).getAge());
               }else {
                   throw new RuntimeException("输入的类型不匹配!");
               }
           }
       };

       TreeSet set = new TreeSet(com);
       set.add(new Person("Tom",23));
       set.add(new Person("FAS",15));
       set.add(new Person("SDF",45));
       set.add(new Person("AEE",45));
       set.add(new Person("WER",32));
       set.add(new Person("AF",20));
       //如果compareTo没有重写年龄的话,就只会有一个对象
       set.add(new Person("AF",50));

       Iterator iterator = set.iterator();
       while(iterator.hasNext()){
           System.out.println(iterator.next());
       }
   }
练习
  public static List duplicateList(List list){
      HashSet set =  new HashSet();
      set.addAll(list);
      return new ArrayList(set);
  }
  @Test
  public void test5(){
      List list = new ArrayList();
      list.add(new Integer(1));
      list.add(new Integer(2));
      list.add(new Integer(2));
      list.add(new Integer(3));
      list.add(new Integer(3));
      List list1 = duplicateList(list);
      for (Object integer : list1){
          System.out.println(integer);
      }
  }
  @Test
  public void test6(){
      HashSet set = new HashSet();
      Person p1 = new Person("AA",1001);
      Person p2 = new Person("BB",1002);

      set.add(p1);
      set.add(p2);

      p1.name = "CC";
      set.remove(p1);
      System.out.println(set);

      set.add(new Person("CC",1001));
      System.out.println(set);
      set.add(new Person("AA",1001));
      System.out.println(set);
  }
}
发布了19 篇原创文章 · 获赞 0 · 访问量 481

猜你喜欢

转载自blog.csdn.net/weixin_43244120/article/details/105497112