概述

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的元素内容变化导致的问题的更多相关文章

  1. jQuery 监听元素内容变化的方法

    我们可以用onchange事件来完成元素值发生改变触发的监听.但是 onchange 比较适用于<input>.<textarea> 以及 <select> 元素. ...

  2. 监控父元素里面子元素内容变化 DOMSubtreeModified

    1监控ul的li的变化情况,并实时输出li的长度 布局: <ul id="isSelected"></ul> <span id="modal ...

  3. js监听dom元素内容变化

    $("#divid").bind('DOMNodeInserted', function(e) { alert('element now contains: ' + $(e.tar ...

  4. Java HashSet对txt文本内容去重(统计小说用过的字或字数)

    Java HashSet对txt文本内容去重(统计小说用过的字或字数) 基本思路: 1.字节流读需要去重的txt文本.(展示demo为当前workspace下名为utf-8.txt的文本) 2.对读取 ...

  5. 《java入门第一季》之HashSet存储元素保证唯一性的代码及图解

    上一篇介绍了HashSet存储自定义自定义对象时应该注意的问题http://blog.csdn.net/qq_32059827/article/details/51580642, 这一篇对其内部结构稍 ...

  6. 读书笔记:《HTML5开发手册》--现有元素的变化

    读书笔记:<HTML5开发手册>-- 现存元素的变化 继续学习HTML5语义化的内容,今天主要介绍一下,HTML5之前的元素经HTML5规范后的语义及一些使用示例. 一.cite HTML ...

  7. input输入框内容变化实时监听

    js实现的文本框内容发生改变立马触发事件简单介绍:本章节介绍一下如何在文本框的内容发生变化的时候,立马触发一个事件执行响应的操作,而不是像是keydown或者keyup事件一样,只能够检测通过键盘输入 ...

  8. 《手把手教你》系列技巧篇(十五)-java+ selenium自动化测试-元素定位大法之By xpath中卷(详细教程)

    1.简介 按宏哥计划,本文继续介绍WebDriver关于元素定位大法,这篇介绍定位倒数二个方法:By xpath.xpath 的定位方法, 非常强大.  使用这种方法几乎可以定位到页面上的任意元素. ...

  9. 《手把手教你》系列技巧篇(十六)-java+ selenium自动化测试-元素定位大法之By xpath下卷(详细教程)

    1.简介 按宏哥计划,本文继续介绍WebDriver关于元素定位大法,这篇介绍定位倒数二个方法:By xpath.xpath 的定位方法, 非常强大.  使用这种方法几乎可以定位到页面上的任意元素. ...

随机推荐

  1. JS把内容动态插入到DIV

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DT ...

  2. Makefile $@,$^,$ 作用

    /* main.c */        #include "mytool1.h"        #include "mytool2.h"        int  ...

  3. [Luogu 2596] ZJOI2006 书架

    [Luogu 2596] ZJOI2006 书架 第一次指针写 FHQ_Treap(省选噩梦数据结构)AC 啦! 省选试机写它,紧张过度失败了. 省选 Day 1 考场写它,写挂了. 省选 Day 1 ...

  4. Jmeter-分布式

    转载自: http://www.51testing.com/html/28/116228-247521.html 由于Jmeter本身的瓶颈,当需要模拟数以千计的并发用户时,使用单台机器模拟所有的并发 ...

  5. 【NOIP】提高组2016 愤怒的小鸟

    [题意]Universal Online Judge [算法]状态压缩型DP [题解]看数据范围大概能猜到是状压了. 根据三点确定一条抛物线,枚举两个点之间的抛物线,再枚举有多少点在抛物线上(压缩为状 ...

  6. PHP做分页查询(查询结果也显示为分页)

    1.先把数据库里所有的数据分页显示在页面,并在显示数据的表格上方加上查询表单. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transit ...

  7. bzoj 1305 二分+最大流判定|贪心

    首先我们二分一个答案mid,在判定是否能举办mid次,那么对于每个次我们可以用最大流根据是否满流(流量为n*mid)来判定,对于每个点我们拆成两个点,分别表示这个人要和他喜欢和不喜欢的人一起跳舞,那么 ...

  8. 线程,JSP,Servlet面试题

    线程编程方面 60.java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 答:有两种实现方法,分别是继承Thread类与实现Runna ...

  9. VMWare虚拟机NAT模式静态IP联网配置

    1.网络连接    vmnet8右键属性ipv4,设置ip为192.168.10.100.如下图: 2.设置虚拟机的网络适配器采用NAT模式 3.vmware工具栏的编辑->虚拟网络编辑器   ...

  10. 在 kernel 下打出 有帶參數的log。 怪異現象與解決方式。

    code battery_log(BAT_LOG_CRTI, "youchihwang abc10010 xxxaaa8-2\r\n"); battery_log(BAT_LOG_ ...