Java集合之Set接口及其实现类精解
作者:叶绿体不忘呼吸 发布时间:2022-01-23 17:27:44
目录
Set接口概述
HashSet实现类
1、HashSet 具有以下特点:
2、HashSet 集合判断两个元素相等的标准
3、向HashSet中添加元素的过程
LinkedHashSet实现类
TreeSet实现类
Set接口概述
1、Set接口是Collection的子接口,set接口没有定义额外的方法,使用的都是Collection接口中的方法。
2、Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个Set 集合中,则添加操作失败。
3、Set:存储无序的、不可重复的数据
(以HashSet为例说明)
①无序性:不等于随机性。存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值。
②不可重复性:保证添加的元素按照equals()判断时,不能返回true。即:相同的元素只能添加一个。
HashSet实现类
1、HashSet 具有以下特点:
①不能保证元素的排列顺序
②HashSet 不是线程安全的
③集合元素可以是 null
2、HashSet 集合判断两个元素相等的标准
两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。因此对于存放在Set容器中的对象,对应的类一定要重写equals()和hashCode()方法,以实现对象相等规则,即:“相等的对象必须具有相等的散列码”。
3、向HashSet中添加元素的过程
我们向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算元素a的哈希值,此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置(索引位置)。接着判断数组此位置上是否已经有元素:
如果此位置上没有其他元素,则元素a添加成功。—>情况1
如果此位置上有其他元素b(或以链表形式存在多个元素),则比较元素a与元素b的hash值:
如果hash值不相同,则元素a添加成功。—> 情况2
如果hash值相同,进而需要调用元素a所在类的equals()方法:
如果equals()返回true,元素a添加失败
如果equals()返回false,则元素a添加成功。—>情况3
对于添加成功的情况2和情况3而言:元素a与已经存在指定索引位置上数据以链表的方式存储。(七上八下)
jdk 7 : 新来元素a放到数组中,指向已存在的旧元素。
jdk 8 : 已存在的旧元素在数组中,指向新来元素a
底层为“数组+链表”,数组初始容量为16,当如果使用率超过0.75(16*0.75=12)就会扩大容量为原来的2倍。(16扩容为32,依次为64,128…等)
重写equals()方法的时候一般都需要同时复写hashCode()方法。通常参与计算hash值的对象的属性也应该参与到equals()中进行计算
LinkedHashSet实现类
1、LinkedHashSet 是 HashSet 的子类,也是根据元素的 hashCode 值来决定元素的存储位置,但它同时使用双向链表维护元素的次序,这使得元素看起来是以插入顺序保存的。
2、LinkedHashSet插入性能略低于 HashSet,但在迭代访问(遍历) Set 里的元素时有很好的性能。
3、LinkedHashSet 不允许集合元素重复。
TreeSet实现类
1、TreeSet 是 SortedSet 接口的实现类,TreeSet 可以确保集合元素处于排序状态。元素应为相同类的对象。
2、TreeSet底层使用红黑树结构存储数据。
3、TreeSet 两种排序方法:自然排序和定制排序。默认情况下,TreeSet 采用自然排序。
4、自然排序
①TreeSet 会调用集合元素的 compareTo(Object obj) 方法来比较元素之间的大小关系,然后将集合元素按条件排列。如果试图把一个对象添加到 TreeSet 时,则该对象的类必须实现 Comparable 接口。实现 Comparable 的类必须重写compareTo(Object obj) 方法,两个对象通过compareTo(Object obj) 方法的返回值来比较大小。
②向 TreeSet 中添加元素时,只有第一个元素无须比较compareTo()方法,后面添
加的所有元素都会调用compareTo()方法进行比较。
③因为只有相同类的两个实例才会比较大小,所以向 TreeSet 中添加的应该是同
一个类的对象。
④对于 TreeSet 集合而言,它判断两个对象是否相等的唯一标准是两个对象通过 compareTo(Object obj) 方法比较的返回值。
import java.util.Iterator;
import java.util.TreeSet;
/**
* @Author: Yeman
* @Date: 2021-09-16-16:48
* @Description:
*/
class Student implements Comparable{
String name;
int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
//姓名从小到大,年龄从大到小排列
public int compareTo(Object o) {
if (o instanceof Student){
Student student = (Student) o;
int nameResult = this.name.compareTo(student.name);
if (nameResult == 0){
return -Integer.compare(this.age,student.age);
}else {
return nameResult;
}
}else throw new RuntimeException("类型不匹配");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class TreeSetTest {
public static void main(String[] args) {
TreeSet treeSet = new TreeSet();
treeSet.add(new Student("Tom",18));
treeSet.add(new Student("Tom",22));
treeSet.add(new Student("jim",18));
treeSet.add(new Student("Anne",19));
treeSet.add(new Student("Lily",25));
treeSet.add(new Student("LiLei",25));
Iterator iterator = treeSet.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
5、定制排序
①定制排序,通过Comparator接口来实现,需要重写compare(T o1,T o2)方法。
②要实现定制排序,需要将实现Comparator接口的实例作为形参传递给TreeSet的构造器。
③仍然只能向TreeSet中添加类型相同的对象。否则发生ClassCastException异常。
④使用定制排序判断两个元素相等的标准是:通过Comparator比较两个元素返回了0。
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
/**
* @Author: Yeman
* @Date: 2021-09-16-16:48
* @Description:
*/
class Student{
String name;
int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class TreeSetTest {
public static void main(String[] args) {
Comparator com = new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof Student && o2 instanceof Student) {
Student student1 = (Student) o1;
Student student2 = (Student) o2;
return Integer.compare(student1.age, student2.age);
} else throw new RuntimeException("类型不匹配");
}
};
TreeSet treeSet = new TreeSet(com);
treeSet.add(new Student("Tom",18));
treeSet.add(new Student("Tom",22));
treeSet.add(new Student("jim",18));
treeSet.add(new Student("Anne",19));
treeSet.add(new Student("Lily",25));
treeSet.add(new Student("LiLei",25));
Iterator iterator = treeSet.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
来源:https://blog.csdn.net/m0_46653805/article/details/120329878


猜你喜欢
- 题目一链表题——链表合并根据给定的两个升序链表合并为一个新的升序链表具体题目如下解法/** * Definition for singly-
- java反射机制是什么反射机制是在运行状态中,可以知道任何一个类的属性和方法,并且调用类的属性和方法;反射机制能够做什么1、判断运行对象的所
- 本文实例讲述了Android基于TextView实现的跑马灯效果。分享给大家供大家参考,具体如下:package sweet.venst.a
- 本文为大家分享了java画出五子棋游戏棋盘的方法,供大家参考,具体内容如下棋盘模块:画五子棋棋盘:19条横线、19条竖线步骤一:显示棋盘我有
- 在主Activity中:listview=(ListView)findViewById(R.id.listview);getData();/
- 错误Mybatis-Plus (简称MP) 是mybatis的一个增强工具,在mybatis的基础上只做增强不做改变,简化了开发效率。其实就
- 在c#中可以遍历指定驱动器或指定目录下嵌套目录中的所有文件或者任意深度的文件。通过遍历可以检索string形式的目录名和文件名,也可以检索
- 在搭建Spring Cloud Eureka环境前先要了解整个架构的组成,常用的基础模式如下图:服务提供者:将springboot服务编写好
- mybatis-spring:@MapperScan注解在demo: springboot+mybatis的示例中,dao层接口使用了注解@
- using System;using System.Collections.Generic;using System.ComponentMo
- 安装JDK 向导进行相关参数设置。如图: 正在安装程序的相关功能,如图: 选择安装的路径,可以自定义,也可以默认路径。如图: 成功安装之
- 本文实例为大家分享了Android实现录音静音降噪的具体代码,供大家参考,具体内容如下需求:客户反馈产品的录音里面很多杂音(因为我们把Cod
- 本文实例为大家分享了C#实现学生成绩管理系统的具体代码,供大家参考,具体内容如下使用链表写学生成绩管理系统链表可以灵活的展示增删改查下面是结
- 本文讲述了Android编程中关于单线程模型的理解与分析。分享给大家供大家参考,具体如下:当一个Android程序启动时,Android系统
- java应用CPU有波动,事后怎么分析?目前我采用的方案是根据CPU负载自动执行jstack,并将文件上传到OSS。 环境:阿里云
- 工程搭建1.File->new->project;2.选择“Spring Initializr”,点击next;(jdk1.8默
- mybatis-plus框架功能很强大,把很多功能都集成了,比如自动生成代码结构,mybatis crud封装,分页,动态数据源等等,附上官
- 多数据源创建数据库CREATE DATABASE mybatis_plus_1;USE mybatis_plus_1;CREATE TABL
- 1、volley 项目地址 https://github.com/smanikandan14/Volley-demo (1)&nb
- 我们初学java的第一个程序是"hello world" public class HelloWorld {