Java集合三:Set简述;方法,问题列举;hashcode;Set查找和删除;

1.Set简述

Set(接口):元素无序,不可以重复(内存地址不可重复),称为集;

常见的是实现类HashSet,即哈希集;

由于HashSet可以出现null元素,又因为其不可以重复,所以做多只能有一个null元素;

HashSet具有良好的存取和查找性能,更适用于频繁存取和查找的场景。


HashSet构造方法


2.方法,问题列举

add()方法:Set只有这一种add()方法

取Set中元素时,因为Set是无序的,所以没有index,此时需要使用迭代器去获取

So如何得到迭代器?→ iterator()方法

Set放到迭代器后,下一步就是遍历迭代器输出:

……………………………………………………

当向Set中添加重复元素时,不会起什么作用,只会浪费时间浪费内存。用Set去重,以前这样用过

删除某个元素:boolean remove(Object o)

                         boolean removeAll(Set set):删除所有集合中所有元素。

!!!注意:当通过传统方法删除集合中满足条件的多个元素时候,会报错(因为Set为了安全,不允许在读取Set的时候再删除元素):

对于这种情况,正确的做法是:将集合中所有满足条件的元素组成一个新的子集合,然后调用集合的removeAll()方法即可,如下示例:

 

判断集合是否为空:isEmpty()


(1) eclipse中自动添加toString()方法

Object类中的 toString()方法用于返回对象的字符串表示,直接打印类就是调用类的toString()方法;一般我们在实际中,习惯重写toString()方法


3.hashcode

Set:不允许存放内存地址一样的元素。

(预先说一下(下面会有解释):向Set中存放数据时候,会先通过hashCode()方法看看,这个数据该放在那个“区块中”,然后通过equals()方法查看在该区块中是否有相同的元素)

Set中自然不能添加相同的字符串,相同的数字,在向Set中添加元素时大概率用到了自动装箱,把数字转成了包装类,而直接add(1)时,1是存放在常量池中的,所以通过add(1)形式添加时候,当数字相同时,其包装类对象就是同一个,所以在哈希算法的情况下,都是相同的,即不能重复添加。这个hashcode值的细节咱可不深究,只需要知道这是个“牛逼”的类似数据库的索引即可

 

问题:

如果,向Set中添加bean类,当new两个各属性信息一样的对象,向Set中添加的时候,是可以添加的,这个时候,看起来是向Set中添加了两个信息完全一样的对象,但其实Set:不允许存放内存地址一样的元素。所以,而,Set中控制不可添加重复元4素的方法主要是hashcode()方法和equals()方法,所以有的时候为了防止两个信息完全一样对象重复添加的问题,需要重写这两个方法。

一般,hashCode()方法我们维持原样不管,面也不用理解该方法的内容;equals()方法可以改一下

 

……………………………………………………

hashCode()方法背后有个哈希表的概念:

哈希表的简要介绍:

如果用ArrayList(没有利用哈希算法)存储100个正整数,这100个数据在内存中是连续的,当我们向查询某个数据是否在该list中时候,需要挨个比较,效率特别低。而哈希表可以解决这个问题。

那么如何使用哈希表嘞?

 哈希表可以理解为通过某种规则将数据进行分类(分块),根据一种计算规则,把数据存放在内存中的不同的“区块中”,存储数据的时候什么数据存在什么“区块中”,这需要一个规则,这个规则其实是根据hashcode,具体的hashcode如何设计和得到需要根据需求来处理。一个好的hashcode的获得,需要严格的算法去完成的,对于一般情况,通过IDE自动生成的hashCode()方法生成的hashcode就够用了,直接拿来用就行了。

下面是一个简单的示例,通过hash规则如下图存放数据,这样当查询数据的时候,可以先根据计算规则,计算该数据在哪个“区块中”,然后就可以直接再在这个“区块中”,通过equals方法去搜寻,这样可以快速地的提高查询速度。以下是一个简单举例。(实际hashcode算法比除三取余复杂的多)。

如当查询97时候,通过97%3 = 1,得知97在1号筒里面,直接在1号桶里去找就行了,提高速度。

注:通过后面的泛型可以知道,一般我们在集合中存放同类的对象,所以在该对象的类中重写hashcode方法和equals方法,就可很好地完成实际的业务需求。?

……………………………………………………

由上面hash表的原理可知,两个对象hashcode相同,只能说明这两个对象是在同一个“区块中”的,那么具体如果在同一个区块中区分不同的对象?这是就需要用到符合实际需求的equals()方法。

通过这样改写equals()方法后,虽然两个对象是不同的对象(内存地址不同),但其各个属相相同,那么在该业务场景下也认为这两个对象是“同一个”对象,这样再向Set中添加该对象元素的时候,就不会出现上面描述的那个重复添加相同属性对象的不符合实际业务需求的问题了

注:疑问,到底什么样的对象会被放在不同的内存区域范围中,查多大的对象会被放在相同的内存区域块中,这个和hashCode()方法有关。​同一个类的两个对象,这两个对象各属性完全一样,那么这两个对象的hashcode值一定相同吗(在不重写hashCode()方法的情况下)。换句话说,在存储过程中,如果hashcode值不一样,就认为不是重复元素,直接存入,用不到equals()方法了吗?还是只有在hashcode值一样的情况下,才会用到equals()方法?待解答。

 


4.Set查找和删除

contains(object o):判断集合中是否有对象o,其他搜寻的是对象时,也可以利用迭代器等,来遍历通过逻辑判断搜寻(其中的效率估计够呛)。

Set的删除见第二部分【方法,问题列举】

……………………………………………………

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值