Java HashSet的元素内容变化导致的问题
概述
HashSet元素引用的对象的内容发生变化,会导致“元素不属于集合”的问题。事实上这个元素还在集合里,但是调用contains方法进行判断,得到的结果却是false。
正文
关于变化
这里所讲的变化是指元素引用的对象的内容的变化,但是对象还是这个对象。比如我们定义如下的field
private Set<Set<Integer>> cache = new HashSet<Set<Integer>>();
我们计划cache里的每一个元素都是一个Set<Integer>的集合。如果我们取出cache的一个元素,然后往这个元素集合中添加一个Integer元素。对于cache来说,这个元素还是这个元素,但是它的内容已经变化了。
关于校验标准
/**
* 校验.<br>
* 从集合中取出的元素反而不属于该集合,则为无效.
* @return
*/
private boolean validate() {
boolean flag = true;
for ( Set<Integer> ele : cache ) {
if (!cache.contains(ele)) {
flag = false;
System.out.println("无效的元素:" + ele);
}
} return flag;
}
测试
我们分为三个测试用例:数据初始化测试、直接更新测试、移除新增测试。
一、数据初始化测试
1. 数据初始化
/**
* 初始化数据.
*/
private void init() {
Integer[][] data = {{1, 2}, {3, 4}, {5}};
for (Integer[] ele : data) {
List<Integer> eleList = Arrays.asList(ele);
Set<Integer> eleSet = new HashSet<Integer>(eleList.size());
eleSet.addAll(eleList); cache.add(eleSet);
} System.out.println(cache);
}
2. 测试
@Test
public void testInit() {
init();
boolean flag = validate();
System.out.println("对初始化的数据进行校验,结果:" + flag);
}
3. 输出结果
[[2, 1], [5], [4, 3]]
对初始化的数据进行校验,结果:true
二、直接更新测试
1. 更新的方法
/**
* 直接修改.
*/
private void update() {
for (Set<Integer> ele : cache) {
if (ele.contains(5)) {
ele.add(6);
break;
}
} System.out.println(cache);
}
2. 测试
@Test
public void testUpdate() {
init();
update(); boolean flag = validate();
System.out.println("对直接修改的数据进行校验,结果:" + flag);
}
3. 输出结果
[[2, 1], [5], [4, 3]]
[[2, 1], [6, 5], [4, 3]]
无效的元素:[6, 5]
对直接修改的数据进行校验,结果:false
三、移除新增测试
1. 移除新增
/**
* 移除添加.
*/
private void removeThenAdd() {
for (Set<Integer> ele : cache) {
if (ele.contains(5)) {
cache.remove(ele);
ele.add(6);
cache.add(ele);
break;
}
} System.out.println(cache);
}
2. 测试
@Test
public void testRA() {
init();
removeThenAdd(); boolean flag = validate();
System.out.println("对移除添加的数据进行校验,结果:" + flag);
}
3. 输出结果
[[2, 1], [5], [4, 3]]
[[2, 1], [4, 3], [6, 5]]
对移除添加的数据进行校验,结果:true
结论
我认为HashSet遍历元素和判断元素是否在集合中的机制是不同的,HashSet中的元素都有一个不同的hashcode,我们直接修改其中的元素,导致其内容和其hashcode对应不上,所以才会有上述的问题。
Java HashSet的元素内容变化导致的问题的更多相关文章
- jQuery 监听元素内容变化的方法
我们可以用onchange事件来完成元素值发生改变触发的监听.但是 onchange 比较适用于<input>.<textarea> 以及 <select> 元素. ...
- 监控父元素里面子元素内容变化 DOMSubtreeModified
1监控ul的li的变化情况,并实时输出li的长度 布局: <ul id="isSelected"></ul> <span id="modal ...
- js监听dom元素内容变化
$("#divid").bind('DOMNodeInserted', function(e) { alert('element now contains: ' + $(e.tar ...
- Java HashSet对txt文本内容去重(统计小说用过的字或字数)
Java HashSet对txt文本内容去重(统计小说用过的字或字数) 基本思路: 1.字节流读需要去重的txt文本.(展示demo为当前workspace下名为utf-8.txt的文本) 2.对读取 ...
- 《java入门第一季》之HashSet存储元素保证唯一性的代码及图解
上一篇介绍了HashSet存储自定义自定义对象时应该注意的问题http://blog.csdn.net/qq_32059827/article/details/51580642, 这一篇对其内部结构稍 ...
- 读书笔记:《HTML5开发手册》--现有元素的变化
读书笔记:<HTML5开发手册>-- 现存元素的变化 继续学习HTML5语义化的内容,今天主要介绍一下,HTML5之前的元素经HTML5规范后的语义及一些使用示例. 一.cite HTML ...
- input输入框内容变化实时监听
js实现的文本框内容发生改变立马触发事件简单介绍:本章节介绍一下如何在文本框的内容发生变化的时候,立马触发一个事件执行响应的操作,而不是像是keydown或者keyup事件一样,只能够检测通过键盘输入 ...
- 《手把手教你》系列技巧篇(十五)-java+ selenium自动化测试-元素定位大法之By xpath中卷(详细教程)
1.简介 按宏哥计划,本文继续介绍WebDriver关于元素定位大法,这篇介绍定位倒数二个方法:By xpath.xpath 的定位方法, 非常强大. 使用这种方法几乎可以定位到页面上的任意元素. ...
- 《手把手教你》系列技巧篇(十六)-java+ selenium自动化测试-元素定位大法之By xpath下卷(详细教程)
1.简介 按宏哥计划,本文继续介绍WebDriver关于元素定位大法,这篇介绍定位倒数二个方法:By xpath.xpath 的定位方法, 非常强大. 使用这种方法几乎可以定位到页面上的任意元素. ...
随机推荐
- Cppcheck代码分析下
1.流解析 解析函数中的可能的代码执行流, 函数实际执行中只会执行代码流中的一条流 分析: 分支语句 if-else ,switch-case 循环语句 while, do-while ...
- PowerDesigner16 活动图
活动是某件事情正在进行的状态.活动在状态机中表现为一个由一系列动作组成 的非原子的执行过程. 活动图是一种描述系统行为的图,它用于展现 参与行为的实体所进行的各种活动的顺序关系.活动图(Activit ...
- Large Class--过大的类--要重构的信号
如果想利用单个类做太多事情,其内往往就会出现太多实例变量.一旦如此,Duplicated Code也就接踵而至. 解决方法: 1.将类内彼此相关的变量,将它们放在一起.使用Extrac ...
- Item 4 ----通过私有构造器强化不可实例化的能力
场景: 在创建工具类的时候,大部分是无需实例化的,实例化对它们没有意义.在这种情况下,创建的类,要确保它是不可以实例化的. 存在问题: 在创建不可实例化的类时,虽然没有定义构造器.但是,客户端在使 ...
- 【LuoguP3038/[USACO11DEC]牧草种植Grass Planting】树链剖分+树状数组【树状数组的区间修改与区间查询】
模拟题,可以用树链剖分+线段树维护. 但是学了一个厉害的..树状数组的区间修改与区间查询.. 分割线里面的是转载的: ----------------------------------------- ...
- 【NOIP】提高组2015 跳石头
[算法]二分查找 [题解]最小值最大化问题. 从1..l内二分枚举答案,将每个答案最少移开的石头数与最大移开数m比较. 精简写法学自:https://vijos.org/p/1981/solution ...
- 安装Vue.js devtools
1.下载安装 https://github.com/vuejs/vue-devtools#vue-devtools 通过以上地址下载安装包,解压以后进入文件,按住shift,点击鼠标右键打开命令窗口 ...
- Pythone3 sys模块
1.sys.argv 可以实现从程序外部向程序传递参数2.sys.exit() 程序中间退出,exit(0)正常退出,其他为异常退出3.sys.getdefaultencoding() 获取系统编码方 ...
- 通过编译函数库来学习GCC【转】
转自:http://blog.csdn.net/u012365926/article/details/51446295 基本概念 什么是库 在windows平台和linux平台下都大量存在着库. 本质 ...
- C#通过反射获取类中的方法和参数个数,反射调用方法带参数
using System; using System.Reflection; namespace ConsoleApp2 { class Program { static void Main(stri ...