集合架构-Set

简介: 集合架构-Set

Set集合介绍

Set简介

Collection集合体系

Collection接口,其子接口有List、Set接口

Set集合其实就是一个接口,HashSet和TreeSet实现了Set接口,所有Set所具备的方法HashSet和TreeSet也是具备的。

Set接口实现类:HashSet 、TreeSet

Set增删改查

实例化 : Set s = new HashSet();

//增加单个元素
s.add("a");
//增加集合
s.addAll(new ArrayList(30));

//删除单个元素
remove("a");
//删除一个集合
removeAll(new ArrayList(30));

说明:Set集合因为是无序,没有自带的更改方法,但是我们可以根据自己需求组合查,删,增,的方法自己写出一个改(看自己领悟能力)。

//根据元素查找
s.contains("a");
//查看集合长度
s.size();

Set集合无序存储的原因

Set集合的底层实现实际上时采用哈希表存储元素

JDK1.8之前:哈希表 = 数组 + 链表 + ( 哈希算法 )

JDK1.8之后:哈希表 = 数组 + 链表 + 红黑树 + ( 哈希算法 )

当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。

一、Set集合特点

1.不可重复加入元素对象

由以下代码可证明

package com.SAME_LOVE;
import java.util.HashSet;
import java.util.Set;
public class Demo01 {
  public static void main(String[] args) {
     Set s = new HashSet();
          s.add("丘比特");
          s.add("马德论");
          s.add("丘比特");
          s.add("马德论");
          s.add("萨斯利");
          System.out.println(s);
  }
}

输出结果为:

2.无序输出

package com.SAME_LOVE;
import java.util.HashSet;
import java.util.Set;
public class Demo01 {
  public static void main(String[] args) {
      //实例化集合
        Set s = new HashSet();
        //增加元素对象
          s.add(new Person(1, "丘比特",22));
          s.add(new Person(2, "马德论",19));
          s.add(new Person(3, "萨斯利",25));
          s.add(new Person(4, "萨斯利",18));
          //循环遍历
          for (Object obj: s) {
             System.out.println(obj);
      }
  }
}
class Person{
  private int id;
  private String name;
  private int age;
  public int getId() {
    return id;
  }
  public void setId(int id) {
    this.id = id;
  }
  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 Person() {
    super();
  }
  public Person(int id, String name, int age) {
    super();
    this.id = id;
    this.name = name;
    this.age = age;
  }
  @Override
  public String toString() {
    return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
  }
}

以上代码执行结果为 如图:

二、Set遍历

foreach

//实例化集合
        Set s = new HashSet();
        //增加元素对象
        s.add("丘比特");
        s.add("马德论");
        s.add("萨斯利");
        for (Object obj: s) {
             System.out.println(obj);
      }

输出结果如下: 马德论  萨斯利  丘比特

迭代器

package com.SAME_LOVE;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Demo01 {
  public static void main(String[] args) {
      //实例化集合
        Set s = new HashSet();
        //增加元素对象
          s.add(new Person(1, "丘比特",22));
          s.add(new Person(2, "马德论",19));
          s.add(new Person(3, "萨斯利",25));
          s.add(new Person(4, "萨斯利",18));
          //循环遍历
          Iterator it = s.iterator();
          while (it.hasNext()) {
              System.out.println(it.next());
          }
  }
}
class Person{
  private int id;
  private String name;
  private int age;
  public int getId() {
    return id;
  }
  public void setId(int id) {
    this.id = id;
  }
  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 Person() {
    super();
  }
  public Person(int id, String name, int age) {
    super();
    this.id = id;
    this.name = name;
    this.age = age;
  }
  @Override
  public String toString() {
    return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
  }
}

三、HashSet去重原理

代码测试

package com.SAME_LOVE;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Demo01 {
  public static void main(String[] args) {
      //实例化集合
        Set s = new HashSet();
        //增加元素对象
          s.add(new Person(1, "丘比特",22));
          s.add(new Person(2, "马德论",19));
          s.add(new Person(2, "马德论",19));
          s.add(new Person(3, "萨斯利",25));
          s.add(new Person(4, "萨斯利",18));
          s.add(new Person(4, "萨斯利",18));
          //循环遍历
          Iterator it = s.iterator();
          while (it.hasNext()) {
              System.out.println(it.next());
          }
  }
}
class Person{
  private int id;
  private String name;
  private int age;
  public int getId() {
    return id;
  }
  public void setId(int id) {
    this.id = id;
  }
  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 Person() {
    super();
  }
  public Person(int id, String name, int age) {
    super();
    this.id = id;
    this.name = name;
    this.age = age;
  }
  @Override
  public String toString() {
    return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
  }
  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + age;
    result = prime * result + id;
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    return result;
  }
  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    Person other = (Person) obj;
    if (age != other.age)
      return false;
    if (id != other.id)
      return false;
    if (name == null) {
      if (other.name != null)
        return false;
    } else if (!name.equals(other.name))
      return false;
    return true;
  }
}

输出结果

如图:

由以上代码测试得出:

最终原理(结论)

  • HashSet去重是有元素对象的hashCode方法和equals方法的返回值决定的
  • 先会调用hashCode方法判断元素对象的属性如果返回值一致说明该集合里面已有该元素对象不能继续增加
  • 如果hashCode方法返回值不一样将调用equals方法进行内容判断有重复已将不能进行增加
  • 在此之前两个方法都必须重写,不然不能进行去重
  • 就算重写hashCode方法和equals方法如果想不进行去重,将hashCode方法返回值定为始终返回一样的值即可

四、TreeSet 自然排序.比较器排序

1.自然排序

提示:进行自然排序操作该对象必须实现java.lang.Comparable接口并且重写compareTo方法,否则会报此异常错误

Exception in thread "main" java.lang.ClassCastException:

com.SAME_LOVE.Person cannot be cast to java.lang.Comparable

代码测试:

package com.SAME_LOVE;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
public class Demo01 {
  public static void main(String[] args) {
      //实例化集合
        HashSet s = new HashSet();
        //增加元素对象
          s.add(new Person(1, "丘比特",22,11000));
          s.add(new Person(2, "马德论",19,24000));
          s.add(new Person(3, "卡卡西",19,15000));
          s.add(new Person(4, "Ikun",25,20000));
          s.add(new Person(5, "小黑子",18,2100));
          s.add(new Person(6, "萨斯利",18,9000));
          //循环遍历
          Iterator it = s.iterator();
          System.out.println("没有排序之前的顺序");
          while (it.hasNext()) {
              System.out.println(it.next());
          }
          //实例化集合
        TreeSet st = new TreeSet();
        //遍历HashSet集合
        for (Object object : s) {
          //加入TreeSet集合之前会调用对象重写的compare方法进行排序
        st.add(object);
      }
        System.out.println("已经排序之后的顺序");
        for (Object obj : st) {
        System.out.println(obj);
      }
  }
}
class Person implements Comparable<Person>{
  private int id;
  private String name;
  private int age;
  private int money;
  public int getId() {
    return id;
  }
  public void setId(int id) {
    this.id = id;
  }
  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 getMoney() {
    return money;
  }
  public void setMoney(int money) {
    this.money = money;
  }
  @Override
  public String toString() {
    return "Person [id=" + id + ", name=" + name + ", age=" + age + ", money=" + money + "]";
  }
  public Person(int id, String name, int age, int money) {
    super();
    this.id = id;
    this.name = name;
    this.age = age;
    this.money = money;
  }
  public Person() {
    super();
  }
  @Override
  public int compareTo(Person o) {
    return this.id - o.id;
  }
}

以上代码执行的输出结果为:

测试得出其原理:

  • 如果想对元素对象其他属性进行排序,修改compareTo方法的返回值即可
  • this比较元素对象是进行升序
  • 元素对象比较this的进行降序

2.构造器使用排序(比较器排序)

提示:进行比较器排序操作该对象必须实现java.lang.Comparable接口,TreeSet在实现java.util.Comparator的匿名内部类并且重写compare方法,否则会报错

代码测试:

package com.SAME_LOVE;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
public class Demo01 {
  public static void main(String[] args) {
      //实例化集合
        TreeSet s = new TreeSet();
        //增加元素对象
          s.add(new Person(1, "丘比特",22,11000));
          s.add(new Person(2, "马德论",19,20000));
          s.add(new Person(3, "卡卡西",25,20000));
          s.add(new Person(4, "Ikun",22,20000));
          s.add(new Person(5, "小黑子",25,9000));
          s.add(new Person(6, "萨斯利",18,9000));
          //循环遍历
          Iterator it = s.iterator();
          System.out.println("没有进行比较器排序之前的顺序");
          while (it.hasNext()) {
              System.out.println(it.next());
          }
          //实例化集合
          TreeSet st = new TreeSet<>(new Comparator<Person>() {
            //需求:在比较Money一样的同时再比较Age进行降序
        @Override
        public int compare(Person o1, Person o2) {
          //Money进行比较降序
          int last =  o2.getMoney() - o1.getMoney();
          //判断Money比较后对于0
          if(last == 0) {
            //在进行Age降序
            return  o2.getAge() - o1.getAge();
          }
          return last;
        }
      });
        //遍历HashSet集合
        for (Object object : s) {
          //加入TreeSet集合之前会调用对象重写的compare方法进行排序
        st.add(object);
      }
        System.out.println("已经进行比较器排序之后的顺序");
        for (Object obj : st) {
        System.out.println(obj);
      }
  }
}
class Person implements Comparable<Person>{
  private int id;
  private String name;
  private int age;
  private int money;
  public int getId() {
    return id;
  }
  public void setId(int id) {
    this.id = id;
  }
  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 getMoney() {
    return money;
  }
  public void setMoney(int money) {
    this.money = money;
  }
  @Override
  public String toString() {
    return "Person [id=" + id + ", name=" + name + ", age=" + age + ", money=" + money + "]";
  }
  public Person(int id, String name, int age, int money) {
    super();
    this.id = id;
    this.name = name;
    this.age = age;
    this.money = money;
  }
  public Person() {
    super();
  }
  @Override
  public int compareTo(Person o) {
    return this.id - o.id;
  }
}

以上代码输出结果为:

由以上测试得出其原理:

  • 先在TreeSet集合内部实现java.util.Comparator的匿名内部类并且重写compare方法
  • 比较器可以对元素对象的属性进行多次比较后进行排序---升序和降序都可
  • 根据所需要求想如何排序修改对比集合中的元素属性即可(本测试要求为:先按Money进行降序,当Money对比返回值一样的同时进行Age就降序【如上一图所示】);
  • 想要修改为升序,将compare方法第一个对象参数放在前面对比
  • 想要修改为降序,则将compare方法第一个对象参数放后面对比
目录
相关文章
|
28天前
|
Java
【Java集合类面试二十三】、List和Set有什么区别?
List和Set的主要区别在于List是一个有序且允许元素重复的集合,而Set是一个无序且元素不重复的集合。
|
3月前
|
Dart
Dart之集合详解(List、Set、Map)
Dart之集合详解(List、Set、Map)
|
3月前
|
存储 JavaScript 前端开发
JavaScript进阶-Map与Set集合
【6月更文挑战第20天】JavaScript的ES6引入了`Map`和`Set`,它们是高效处理集合数据的工具。`Map`允许任何类型的键,提供唯一键值对;`Set`存储唯一值。使用`Map`时,注意键可以非字符串,用`has`检查键存在。`Set`常用于数组去重,如`[...new Set(array)]`。了解它们的高级应用,如结构转换和高效查询,能提升代码质量。别忘了`WeakMap`用于弱引用键,防止内存泄漏。实践使用以加深理解。
63 3
|
1月前
|
Java 程序员 C语言
赶快收藏!全网最佳Set集合详解:HashSet、TreeSet!
面试官:那TreeSet要怎么定制排序?TreeSet的自定义排序我们要利用Comparator接口,通过向TreeSet传入自定义排序规则的Comparator来实现。官方源码是这么解释的,南友们看一看。// 构造一个新的空树集,根据指定的比较器进行排序。// 插入到集合中的所有元素都必须能够通过指定的比较器相互比较: comparator. compare(e1, e2)不得对集合中的任何元素e1和e2抛出ClassCastException。
赶快收藏!全网最佳Set集合详解:HashSet、TreeSet!
|
1月前
|
存储 安全 Java
java集合框架复习----(4)Map、List、set
这篇文章是Java集合框架的复习总结,重点介绍了Map集合的特点和HashMap的使用,以及Collections工具类的使用示例,同时回顾了List、Set和Map集合的概念和特点,以及Collection工具类的作用。
java集合框架复习----(4)Map、List、set
|
19天前
|
索引 Python 容器
为什么Python中会有集合set类型?
为什么Python中会有集合set类型?
|
30天前
|
存储 NoSQL 算法
Redis6入门到实战------ 三、常用五大数据类型(列表(List)、集合(Set)、哈希(Hash)、Zset(sorted set))
这是关于Redis 6入门到实战的文章,具体内容涉及Redis的五大数据类型:列表(List)、集合(Set)、哈希(Hash)、有序集合(Zset(sorted set))。文章详细介绍了这些数据类型的特点、常用命令以及它们背后的数据结构。如果您有任何关于Redis的具体问题或需要进一步的帮助,请随时告诉我。
|
28天前
|
Java
【Java集合类面试二十二】、Map和Set有什么区别?
该CSDN博客文章讨论了Map和Set的区别,但提供的内容摘要并未直接解释这两种集合类型的差异。通常,Map是一种键值对集合,提供通过键快速检索值的能力,而Set是一个不允许重复元素的集合。
|
1月前
|
存储 Java
java集合框架复习----(3)Set
这篇文章详细介绍了Java集合框架中的Set集合,包括HashSet和TreeSet的特点、实现原理和使用示例,展示了Set集合的无序性、元素唯一性以及如何通过自定义比较器实现元素的排序。
|
1月前
|
Python
python集合类型 (Set Types)
【8月更文挑战第3天】
50 9