博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java容器-Set接口
阅读量:4203 次
发布时间:2019-05-26

本文共 7293 字,大约阅读时间需要 24 分钟。

1. Set 接口介绍

Set 接口继承自 Collection,Set 接口中没有新增方法,方法和 Collection 保持完全一致。我们在前面通过 List 学习的方法,在 Set 中仍然适用。

2. Set 接口特点

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

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

3. HashSet 容器类

HashSet 是一个没有重复元素的集合,不保证元素的顺序。而且 HashSet 允许有 null 元素。HashSet 是采用哈希算法实现,底层实际是用 HashMap 实现的(HashSet 本质就是一个简化版的 HashMap),因此,查询效率和增删效率都比较高。

3.1. HashSet 的使用

import java.util.HashSet;import java.util.Set;public class HashSetTest01 {
public static void main(String[] args) {
//实例化HashSet Set
set = new HashSet<>(); //添加元素 set.add("a"); set.add("b"); set.add("c"); set.add("d"); //获取元素,在HashSet中没有索引,所以没有对应的get(int index)方法 for (String str: set){
System.out.println(str); } //删除元素,删除成功返回true,否则返回false set.remove("a"); //获取元素个数 int size = set.size(); }}

3.2 HashSet 存储特征分析

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

  • 无序:
    在 HashSet 中底层是使用 HashMap 存储元素的。HashMap 底层使用的是数组与链表实现元素的存储。元素在数组中存放时,并不是有序存放的也不是随机存放的,而是对元素的48哈希值进行运算决定元素在数组中的位置。
  • 不重复:
    当两个元素的哈希值进行运算后得到相同的在数组中的位置时,会调用元素的 equals()方法判断两个元素是否相同。如果元素相同则不会添加该元素,如果不相同则会使用单向链表保存该元素。

3.3 通过 HashSet 存储自定义对象

3.3.1 创建 Users 对象

//创建User类import java.util.Objects;public class Users{
private String username; private int userage; public Users(String username, int userage) {
this.username = username; this.userage = userage; } 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 boolean equals(Object o) {
if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Users user = (Users) o; return Objects.equals(username, user.username) && Objects.equals(userage, user.userage); } @Override public int hashCode() {
return Objects.hash(username, userage); } @Override public String toString() {
return "User{" + "username='" + username + '\'' + ", userage='" + userage + '\'' + '}'; }}

3.3.2 在 HashSet 中存储 Users 对象

import java.util.HashSet;import java.util.Objects;import java.util.Set;public class HashSetTest02 {
public static void main(String[] args) {
//实例化HashSet,存放User对象 Set
users = new HashSet<>(); Users user1 = new Users("张三",18); Users user2 = new Users("李四",20); Users user3 = new Users("王五",18); users.add(user1); users.add(user2); users.add(user3); for (Users user: users){
System.out.println(user); } }}

4. TreeSet 容器类

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

排序规则实现方式:

  • 通过元素自身实现比较规则。
  • 通过比较器指定比较规则。

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

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

4.1.1 创建 User 类

//创建User类import java.util.Objects;public class User implements Comparable
{
private String username; private int userage; public User(String username, int userage) {
this.username = username; this.userage = userage; } 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 boolean equals(Object o) {
if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; return Objects.equals(username, user.username) && Objects.equals(userage, user.userage); } @Override public int hashCode() {
return Objects.hash(username, userage); } @Override public String toString() {
return "User{" + "username='" + username + '\'' + ", userage='" + userage + '\'' + '}'; } //定义比较规则,正数:大;负数:小;0:相等 @Override public int compareTo(User o) {
//按年龄排序 if (this.userage > o.getUserage()){
return 1; } //年龄相等按姓名排序 if (this.userage == o.getUserage()){
return username.compareTo(o.getUsername()); } return -1; }}

4.1.2 在 TreeSet 中存放 Users 对象

import java.util.Objects;import java.util.Set;import java.util.TreeSet;public class TreeSetTest01 {
public static void main(String[] args) {
//实例化TreeSet,存放User对象 Set
users = new TreeSet<>(); User user1 = new User("张三",18); User user2 = new User("李四",20); User user3 = new User("王五",18); users.add(user1); users.add(user2); users.add(user3); for (User user: users){
System.out.println(user); } }}

4.2 通过比较器实现比较规则

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

4.2.1 创建 Student 类

import java.util.Objects;public class Student {
private String name; private int age; public Student(String name, int age) {
this.name = name; this.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 String toString() {
return "Student{" + "name='" + name + '\'' + ", 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; return age == student.age && Objects.equals(name, student.name); } @Override public int hashCode() {
return Objects.hash(name, age); }}

4.2.2 创建比较器

import java.util.Comparator;public class StudentComparator implements Comparator
{
@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; }}

4.2.3 在 TreeSet 中存储 Users 对象

import java.util.Set;import java.util.TreeSet;public class TreeSetTest01 {
public static void main(String[] args) {
Set
set2 = new TreeSet<>(new StudentComparator()); Student s = new Student("张三",18); Student s1 = new Student("李四",22); Student s2 = new Student("王五",22); set2.add(s); set2.add(s1); set2.add(s2); for(Student student:set2){
System.out.println(student); } }}

转载地址:http://dqpli.baihongyu.com/

你可能感兴趣的文章
9.PyTorch实现MNIST(手写数字识别)(2卷积1全连接)
查看>>
hdu 3460 Ancient Printer(trie tree)
查看>>
中间数
查看>>
queue基本操作函数
查看>>
Gym 101196D Lost in Translation(BFS)
查看>>
KMP求前缀函数(next数组)
查看>>
KMP
查看>>
poj 3863Business Center
查看>>
C#基本语法里几点和C不一样的地方
查看>>
Libpcap库编程指南--分析数据包
查看>>
LintCode 二叉树的路径和
查看>>
字符编码笔记:ASCII,Unicode 和 UTF-8
查看>>
C++中的Unicode编码:wchar, UTF-8,UTF-16,UTF-32
查看>>
C++中const的用法:使代码更加健壮
查看>>
C++ 11:delete关键词和一条《Effective C++》的过时条款
查看>>
Google C++ 风格指南 :尽可能用 sizeof(varname) 代替 sizeof(type).
查看>>
C++中的委托构造
查看>>
RTP/RTCP 和 SRTP/SRTCP协议
查看>>
AES加密算法(Rijndael算法)
查看>>
WebRTC简介与代码架构
查看>>