Java集合系列:Set解析
Set集合的特点:
不能存储相同的元素,同时因为其是一个抽象的接口:所以不能直接实例化一个set对象。(Set s = new Set() )错误
该接口主要继承于Collections接口,所以具有Collection的一些常见的方法。
对象的相等性:
引用到堆上同一个对象的两个引用是相等的。如果对两个引用调用hashCode方法,会得到相同的结果,如果对象所属的类没有覆盖Object的hashCode方法的话,hashCode会返回每个对象特有的序号(java是依据对象的内存地址计算出的此序号),所以两个不同的对象的hashCode值是不可能相等的。
如果想要让两个不同的Person对象视为相等的,就必须覆盖Object继下来的hashCode方法和equals方法,因为Object hashCode方法返回的是该对象的内存地址,所以必须重写hashCode方法,才能保证两个不同的对象具有相同的hashCode,同时也需要两个不同对象比较equals方法会返回true
一般最常用的两种接口:
- HashSet:存储的对象为无序状态,后加入的对象会把前面相同的对象覆盖,
- TreeSet:将里面的元素按照字典顺序默认排序。
常见的方法:
Sr.No. | Method & Description |
---|---|
1 |
add( ) 向集合中添加元素 |
2 |
clear( ) 去掉集合中所有的元素 |
3 |
contains( ) 判断集合中是否包含某一个元素 |
4 |
isEmpty( ) 判断集合是否为空 |
5 |
iterator( ) 主要用于递归集合,返回一个Iterator()对象 |
6 |
remove( ) 从集合中去掉特定的对象 |
7 |
size( ) 返回集合的大小 |
HashSet特点:
哈希表边存放的是哈希值。HashSet存储元素的顺序并不是按照存入时的顺序(和List显然不同) 是按照哈希值来存的所以取数据也是按照哈希值取得。
Set集合是不能存入重复元素的集合,那么HashSet也是具备这一特性的。HashSet会通过元素的hashcode()和equals方法进行判断元素师否重复。
当你试图把对象加入HashSet时,HashSet会使用对象的hashCode来判断对象加入的位置。同时也会与其他已经加入的对象的hashCode进行比较,如果没有相等的hashCode,HashSet就会假设对象没有重复出现。
简单一句话,如果对象的hashCode值是不同的,那么HashSet会认为对象是不可能相等的。
因此我们自定义类的时候需要重写hashCode,来确保对象具有相同的hashCode值。
如果元素(对象)的hashCode值相同,是不是就无法存入HashSet中了? 当然不是,会继续使用equals 进行比较.如果 equals为true 那么HashSet认为新加入的对象重复了,所以加入失败。如果equals 为false那么HashSet 认为新加入的对象没有重复.新元素可以存入。
总结:
元素的哈希值是通过元素的hashcode方法 来获取的, HashSet首先判断两个元素的哈希值,如果哈希值一样(如果哈希值不相同就不会调用equals方法)会比较equals方法 如果 equals结果为true ,HashSet就视为同一个元素。如果equals 为false就不是同一个元素。
哈希值相同equals为false的元素是怎么存储呢,就是在同样的哈希值下顺延(可以认为哈希值相同的元素放在一个哈希桶中)。也就是哈希值一样的存一列。
Set<Integer> set= new TreeSet<>();
int a = 1;
int b = 8;
int c = 3;set.add(a);
set.add(b);
set.add(c);//遍历集合test 利用foreach遍历 //输出结果:1 3 8 for (Integer value : set) {System.out.print(value+" ");} //利用Iterator实现遍历
Iterator<Integer> value = set.iterator();
while (value.hasNext()) {int s = value.next();System.out.print(s+" ");
} //输出结果:1 3 8
简述TreeSet排序规则:
方式一:元素自身具备比较性
元素自身具备比较性,需要元素实现Comparable接口,重写compareTo方法,也就是让元素自身具备比较性,这种方式叫做元素的自然排序也叫做默认排序。
方式二:容器具备比较性
当元素自身不具备比较性,或者自身具备的比较性不是所需要的。那么此时可以让容器自身具备。需要定义一个类实现接口Comparator,重写compare方法,并将该接口的子类实例对象作为参数传递给TreeMap集合的构造方法。
注意:当Comparable比较方式和Comparator比较方式同时存在时,以Comparator的比较方式为主;
注意:在重写compareTo或者compare方法时,必须要明确比较的主要条件相等时要比较次要条件。(假设姓名和年龄一直的人为相同的人,如果想要对人按照年龄的大小来排序,如果年龄相同的人,需要如何处理?不能直接return 0,因为可能姓名不同(年龄相同姓名不同的人是不同的人)。此时就需要进行次要条件判断(需要判断姓名),只有姓名和年龄同时相等的才可以返回0.)
通过return 0来判断唯一性。
问题:为什么使用TreeSet存入字符串,字符串默认输出是按升序排列的?因为字符串实现了一个接口,叫做Comparable 接口.字符串重写了该接口的compareTo 方法,所以String对象具备了比较性.那么同样道理,我的自定义元素(例如Person类,Book类)想要存入TreeSet集合,就需要实现该接口,也就是要让自定义对象具备比较性.
存入TreeSet集合中的元素要具备比较性.
比较性要实现Comparable接口,重写该接口的compareTo方法
TreeSet属于Set集合,该集合的元素是不能重复的,TreeSet如何保证元素的唯一性
通过compareTo或者compare方法中的来保证元素的唯一性。
添加的元素必须要实现Comparable接口。当compareTo()函数返回值为0时,说明两个对象相等,此时该对象不会添加进来。
比较器接口
----| ComparablecompareTo(Object o) 元素自身具备比较性
----| Comparatorcompare( Object o1, Object o2 ) 给容器传入比较器
TreeSet集合排序的两种方式:
一,让元素自身具备比较性。
也就是元素需要实现Comparable接口,覆盖compareTo 方法。
这种方式也作为元素的自然排序,也可称为默认排序。
年龄按照搜要条件,年龄相同再比姓名。
public class Demo4 {public static void main(String[] args) {TreeSet ts = new TreeSet();ts.add(new Person("aa", 20, "男"));ts.add(new Person("bb", 18, "女"));ts.add(new Person("cc", 17, "男"));ts.add(new Person("dd", 17, "女"));ts.add(new Person("dd", 15, "女"));ts.add(new Person("dd", 15, "女"));System.out.println(ts);System.out.println(ts.size()); // 5}
}class Person implements Comparable {private String name;private int age;private String gender;public Person() {}public Person(String name, int age, String gender) {this.name = name;this.age = age;this.gender = gender;}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 String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}@Overridepublic int hashCode() {return name.hashCode() + age * 37;}public boolean equals(Object obj) {System.err.println(this + "equals :" + obj);if (!(obj instanceof Person)) {return false;}Person p = (Person) obj;return this.name.equals(p.name) && this.age == p.age;}public String toString() {return "Person [name=" + name + ", age=" + age + ", gender=" + gender+ "]";}@Overridepublic int compareTo(Object obj) {Person p = (Person) obj;System.out.println(this+" compareTo:"+p);if (this.age > p.age) {return 1;}if (this.age < p.age) {return -1;}return this.name.compareTo(p.name);}}
运行结果:
Person [name=aa, age=20, gender=男] compareTo:Person [name=aa, age=20, gender=男]
Person [name=bb, age=18, gender=女] compareTo:Person [name=aa, age=20, gender=男]
Person [name=cc, age=17, gender=男] compareTo:Person [name=aa, age=20, gender=男]
Person [name=cc, age=17, gender=男] compareTo:Person [name=bb, age=18, gender=女]
Person [name=dd, age=17, gender=女] compareTo:Person [name=bb, age=18, gender=女]
Person [name=dd, age=17, gender=女] compareTo:Person [name=cc, age=17, gender=男]
Person [name=dd, age=15, gender=女] compareTo:Person [name=bb, age=18, gender=女]
Person [name=dd, age=15, gender=女] compareTo:Person [name=cc, age=17, gender=男]
Person [name=dd, age=15, gender=女] compareTo:Person [name=bb, age=18, gender=女]
Person [name=dd, age=15, gender=女] compareTo:Person [name=cc, age=17, gender=男]
Person [name=dd, age=15, gender=女] compareTo:Person [name=dd, age=15, gender=女]
[Person [name=dd, age=15, gender=女], Person [name=cc, age=17, gender=男], Person [name=dd, age=17, gender=女], Person [name=bb, age=18, gender=女], Person [name=aa, age=20, gender=男]]
5
二,让容器自身具备比较性,自定义比较器。
需求:当元素自身不具备比较性,或者元素自身具备的比较性不是所需的。
那么这时只能让容器自身具备。
定义一个类实现Comparator 接口,覆盖compare方法。
并将该接口的子类对象作为参数传递给TreeSet集合的构造函数。
当Comparable比较方式,及Comparator比较方式同时存在,以Comparator
public class Demo5 {public static void main(String[] args) {TreeSet ts = new TreeSet(new MyComparator());ts.add(new Book("think in java", 100));ts.add(new Book("java 核心技术", 75));ts.add(new Book("现代操作系统", 50));ts.add(new Book("java就业教程", 35));ts.add(new Book("think in java", 100));ts.add(new Book("ccc in java", 100));System.out.println(ts); }
}class MyComparator implements Comparator {public int compare(Object o1, Object o2) {Book b1 = (Book) o1;Book b2 = (Book) o2;System.out.println(b1+" comparator "+b2);if (b1.getPrice() > b2.getPrice()) {return 1;}if (b1.getPrice() < b2.getPrice()) {return -1;}return b1.getName().compareTo(b2.getName());}}class Book {private String name;private double price;public Book() {}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}public Book(String name, double price) {this.name = name;this.price = price;}@Overridepublic String toString() {return "Book [name=" + name + ", price=" + price + "]";}}
运行结果:
Book [name=think in java, price=100.0] comparator Book [name=think in java, price=100.0]
Book [name=java 核心技术, price=75.0] comparator Book [name=think in java, price=100.0]
Book [name=现代操作系统, price=50.0] comparator Book [name=think in java, price=100.0]
Book [name=现代操作系统, price=50.0] comparator Book [name=java 核心技术, price=75.0]
Book [name=java就业教程, price=35.0] comparator Book [name=java 核心技术, price=75.0]
Book [name=java就业教程, price=35.0] comparator Book [name=现代操作系统, price=50.0]
Book [name=think in java, price=100.0] comparator Book [name=java 核心技术, price=75.0]
Book [name=think in java, price=100.0] comparator Book [name=think in java, price=100.0]
Book [name=ccc in java, price=100.0] comparator Book [name=java 核心技术, price=75.0]
Book [name=ccc in java, price=100.0] comparator Book [name=think in java, price=100.0]
[Book [name=java就业教程, price=35.0], Book [name=现代操作系统, price=50.0], Book [name=java 核心技术, price=75.0], Book [name=ccc in java, price=100.0], Book [name=think in java, price=100.0]]
使用HashSet存储自定义对象,并尝试添加重复对象(对象的重复的判定)
public class Demo4 {public static void main(String[] args) {HashSet hs = new HashSet();hs.add(new Person("jack", 20));hs.add(new Person("rose", 20));hs.add(new Person("hmm", 20));hs.add(new Person("lilei", 20));hs.add(new Person("jack", 20));Iterator it = hs.iterator();while (it.hasNext()) {Object next = it.next();System.out.println(next);}}
}class Person {private String name;private int age;Person() {}public Person(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;}@Overridepublic int hashCode() {System.out.println("hashCode:" + this.name);return this.name.hashCode() + age * 37;}@Overridepublic boolean equals(Object obj) {System.out.println(this + "---equals---" + obj);if (obj instanceof Person) {Person p = (Person) obj;return this.name.equals(p.name) && this.age == p.age;} else {return false;}}@Overridepublic String toString() {return "Person@name:" + this.name + " age:" + this.age;}}
运行结果:
hashCode:jack
hashCode:rose
hashCode:hmm
hashCode:lilei
hashCode:jack
Person@name:jack age:20---equals---Person@name:jack age:20
Person@name:jack age:20
Person@name:lilei age:20
Person@name:rose age:20
Person@name:hmm age:20
Java集合系列:Set解析相关推荐
- Java 集合系列06: Vector深入解析
戳上面的蓝字关注我们哦! 精彩内容 精选java等全套视频教程 精选java电子图书 大数据视频教程精选 java项目练习精选 概论 这是接着以前的文章分享的,这里给出以前的文章的连接,供小伙伴们回顾 ...
- Java 集合系列03之 ArrayList详细介绍(源码解析)和使用示例
转载自 Java 集合系列03之 ArrayList详细介绍(源码解析)和使用示例 第1部分 ArrayList介绍 ArrayList简介 ArrayList 是一个数组队列,相当于 动态数组.与 ...
- Java 集合系列目录(Category)
Java 集合系列目录(Category) 转自:Java 集合系列目录(Category) 01. Java 集合系列01之 总体框架 02. Java 集合系列02之 Collection架构 0 ...
- Java 集合系列 16 HashSet
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
- 新手菜鸟 Java 集合系列目录(Category)
Java 集合系列01之 总体框架 http://www.cnblogs.com/skywang12345/p/3308498.html (笔记:Java集合是java提供的工具包,包含了常用的数据结 ...
- Java 集合系列02之 Collection架构
概要 首先,我们对Collection进行说明.下面先看看Collection的一些框架类的关系图: Java 集合系列02之 Collection架构 Collection是一个接口,它主要的两个分 ...
- Java 集合系列(一)
Java集合系列文章将以思维导图为主要形式来展示知识点,让零碎的知识形成体系. 这篇文章主要介绍的是[Java 集合的基本知识],即Java 集合简介. 毕业出来一直使用 PHP 进行开发,对于大学所 ...
- 深入Java集合系列之五:PriorityQueue
转载自 深入Java集合系列之五:PriorityQueue 前言 今天继续来分析一下PriorityQueue的源码实现,实际上在Java集合框架中,还有ArrayDeque(一种双端队列),这里 ...
- Java 集合系列04之 fail-fast总结
转载自 Java 集合系列04之 fail-fast总结 概要 前面,我们已经学习了ArrayList.接下来,我们以ArrayList为例,对Iterator的fail-fast机制进行了解.内 ...
- Java集合系列之四大常用集合(ArrayList、LinkedList、HashSet、HashMap)的用法
Java集合系列之四大常用集合(ArrayList.LinkedList.HashSet.HashMap)的用法 ArrayList ArrayList就是传说中的动态数组,用MSDN中的说法,就是A ...
最新文章
- 一文总结词向量的计算、评估与优化
- wordpress php执行短代码_【漏洞通告】PHP远程代码执行漏洞(CVE-2019-11043)
- C++实现选择排序(附完整源码)
- [渝粤教育] 西南科技大学 计算机网络应用基础 在线考试复习资料2021版(1)
- Java JSP EL
- git快速入门 push/clone/reset/merge/切换分支全都有
- 数十亿个 Wi-Fi 设备存在缺陷,通信易被窃听!
- python 文件 解析ddl_BKM ? 35期 — Python解析ANSYS文件
- 毫末追击智能驾驶1000天,对战蔚小理将现胜负手
- Flask基础--思维导图
- 保龄球记分程序c语言,老鸟救命~关于保龄球记分规则的程序
- 常见的Cracker攻击手法
- 捉奸游戏之后,中年危机游戏也来了。。
- 绿色债券数据最新(2014-2023年)
- [PHP]学生成绩管理系统
- 最近喜欢的几款乐器和民谣
- 数据分析真题日刷 | 网易2018校招数据分析师笔试卷
- 双鱼林php生成器,双鱼林php代码生成器 v2.0 完整版
- 在App Store和Google Play上推广应用程序
- 小米android9使用全屏,小米8应用怎么全屏显示 小米8应用全屏运行设置方法
热门文章
- 机房收费系统-- MDI子窗体显示技巧
- linux下python 2.4升级到 python 2.5
- anaconda安装keras_关于yolo模型的试安装及关于现阶段安排的一点想法
- (原创)3.2 AddOwner和OverrideMetadata的区别
- Qt在线/离线安装包下载网址和说明
- 《Design patterns》读书笔记
- 利用shell和iptables实现自动拒绝恶意试探连接SSH服务
- CodeVS 3027 线段覆盖2(DP)
- leetcode最长递增子序列问题
- 深刻理解HDFS工作机制