JAVA深化_12——容器,Set接口介绍(HashSet,TreeSet)存储特征详解

本文介绍了Set接口的基本概念,重点讲解了HashSet和TreeSet的使用,包括添加、删除元素、无序性和不可重复性,以及如何通过重写equals()和hashCode()方法存储自定义对象。同时,还涉及了TreeSet的排序机制和通过比较器实现排序规则。
摘要由CSDN通过智能技术生成

Set接口介绍

Set接口继承自Collection接口,Set接口中没有新增方法,它和Collection接口保持完全一致。我们在前面学习List接口的使用方式,在Set中仍然适用。因此,学习Set的使用将没有任何难度。

Set接口特点

Set特点:无序、不可重复。无序指Set中的元素没有索引,我们只能遍历查找;不可重复指不允许加入重复的元素。更确切地讲,新元素如果和Set中某个元素通过equals()方法对比为true,则只能保留一个。

Set常用的实现类有:HashSet、TreeSet等,我们一般使用HashSet。

HashSet容器的使用

==HashSet是Set接口的实现类。==是Set存储特征的具体实现。

public class HashSetTest {
  public static void main(String[] args) {
    //实例化HashSet
    Set<String> set = new HashSet<>();
    //添加元素
    set.add("a");
    set.add("b1");
    set.add("c2");
    set.add("d");
    set.add("a");


    //获取元素,在Set容器中没有索引,所以没有对应的get(int index)方法
    for(String str: set){
      System.out.println(str);
     }
    System.out.println("--------------------");
    //删除元素
    boolean flag = set.remove("c2");
    System.out.println(flag);
    for(String str: set){
      System.out.println(str);
     }
    System.out.println("------------------------");
    int size = set.size();
    System.out.println(size);
   }
}

HashSet存储特征分析

HashSet 是一个不保证元素的顺序且没有重复元素的集合,是线程不安全的。HashSet允许有null 元素。

无序:

==在HashSet中底层是使用HashMap存储元素的。HashMap底层使用的是数组与链表实现元素的存储。==元素在数组中存放时,并不是有序存放的也不是随机存放的,而是对元素的哈希值进行运算决定元素在数组中的位置。

不重复:

当两个元素的哈希值进行运算后得到相同的在数组中的位置时,会调用元素的equals()方法判断两个元素是否相同。如果元素相同则不会添加该元素,如果不相同则会使用单向链表保存该元素。

通过HashSet存储自定义对象

<一定要重写自定义对象的HashCode()和equals()方法>

创建Users对象

public class Users {
  private String username;
  private int userage;


  public Users(String username, int userage) {
    this.username = username;
    this.userage = userage;
   }


  public Users() {
   }


  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;


    Users users = (Users) o;


    if (userage != users.userage) return false;
    return username != null ? username.equals(users.username) : users.username == null;
   }


  @Override
  public int hashCode() {
    int result = username != null ? username.hashCode() : 0;
    result = 31 * result + userage;
    return result;
   }


  public String getUsername() {
    return username;
   }


  public void setUsername(String username) {
    this.username = username;
   }


  public int getUserage() {
    return userage;
   }


  public void setUserage(int userage) {
    this.userage = userage;
   }


  @Override
  public String toString() {
    return "Users{" +
        "username='" + username + '\'' +
        ", userage=" + userage +
        '}';
   }
}

在HashSet中存储Users对象

public class HashSetTest2 {
  public static void main(String[] args) {
    //实例化HashSet
    Set<Users> set = new HashSet<>();
    Users u = new Users("zhangsan",18);
    Users u1 = new Users("zhangsan",18);
    set.add(u);
    set.add(u1);
    System.out.println(u.hashCode());
    System.out.println(u1.hashCode());
    for(Users users:set){
      System.out.println(users);
     }
   }
}


TreeSet容器的使用

TreeSet实现了Set接口,它是一个可以对元素进行排序的容器。底层实际是用TreeMap实现的,内部维持了一个简化版的TreeMap,通过key来存储元素。 TreeSet内部需要对存储的元素进行排序,因此,我们需要给定排序规则。

排序规则实现方式:

  • 通过元素自身实现比较规则。
  • 通过比较器指定比较规则。
public class TreeSetTest {
  public static void main(String[] args) {
    //实例化TreeSet
    Set<String> set = new TreeSet<>();
    //添加元素
    set.add("c");
    set.add("a");
    set.add("d");
    set.add("b");
    set.add("a");


    //获取元素
    for(String str :set){
      System.out.println(str);
     }
   }
}

通过元素自身实现比较规则

在元素自身实现比较规则时,需要实现Comparable接口中的compareTo方法,该方法中用来定义比较规则。TreeSet通过调用该方法来完成对元素的排序处理。

创建Users类

public class Users implements Comparable<Users>{
  private String username;
  private int userage;


  public Users(String username, int userage) {
    this.username = username;
    this.userage = userage;
   }


  public Users() {
   }


  @Override
  public boolean equals(Object o) {
    System.out.println("equals...");
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;


    Users users = (Users) o;


    if (userage != users.userage) return false;
    return username != null ? username.equals(users.username) : users.username == null;
   }


  @Override
  public int hashCode() {
    int result = username != null ? username.hashCode() : 0;
    result = 31 * result + userage;
    return result;
   }


  public String getUsername() {
    return username;
   }


  public void setUsername(String username) {
    this.username = username;
   }


  public int getUserage() {
    return userage;
   }


  public void setUserage(int userage) {
    this.userage = userage;
   }


  @Override
  public String toString() {
    return "Users{" +
        "username='" + username + '\'' +
        ", userage=" + userage +
        '}';
   }


  //定义比较规则
  //正数:大,负数:小,0:相等
  @Override
  public int compareTo(Users o) {
    if(this.userage > o.getUserage()){
      return 1;
     }
    if(this.userage == o.getUserage()){
      return this.username.compareTo(o.getUsername());
     }
    return -1;
   }
}

Set<Users> set1 = new TreeSet<>();
Users u = new Users("zhangsan",18);
Users u1 = new Users("zhouxinchi",22);
Users u2 = new Users("chenglong",22);
set1.add(u);
set1.add(u1);
set1.add(u2);
for(Users users:set1){
  System.out.println(users);
}

通过比较器实现比较规则

通过比较器定义比较规则时,我们需要单独创建一个比较器,比较器需要实现Comparator接口中的compare方法来定义比较规则。**在实例化TreeSet时将比较器对象交给TreeSet来完成元素的排序处理。**此时元素自身就不需要实现比较规则了。

创建Student类

public class Student {
  private String name;
  private int age;


  public Student(String name, int age) {
    this.name = name;
    this.age = age;
   }


  public Student() {
   }


  @Override
  public String toString() {
    return "Student{" +
        "name='" + name + '\'' +
        ", age=" + age +
        '}';
   }


  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;
   }


  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;


    Student student = (Student) o;


    if (age != student.age) return false;
    return name != null ? name.equals(student.name) : student.name == null;
   }


  @Override
  public int hashCode() {
    int result = name != null ? name.hashCode() : 0;
    result = 31 * result + age;
    return result;
   }
}

创建比较器

public class StudentComparator implements Comparator<Student> {


  //定义比较规则
  @Override
  public int compare(Student o1, Student o2) {
    if(o1.getAge() > o2.getAge()){
      return 1;
     }
    if(o1.getAge() == o2.getAge()){
      return o1.getName().compareTo(o2.getName());
     }
    return -1;
   }
}

public class TreeSetTest3 {
  public static void main(String[] args) {
    //创建TreeSet容器,并给定比较器对象
    Set<Student> set = new TreeSet<>(new StudentComparator());
    Student s = new Student("zhangsan",18);
    Student s1 = new Student("zhouxinchi",22);
    Student s2 = new Student("sxtchenglong",22);
    set.add(s);
    set.add(s1);
    set.add(s2);
    for(Student student:set){
      System.out.println(student);
     }
   }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值