手机版
你好,游客 登录 注册
背景:
阅读新闻

Java HashSet的元素内容变化导致的问题

[日期:2015-12-24] 来源:Linux社区  作者:ywjy [字体: ]

概述

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对应不上,所以才会有上述的问题。

本文永久更新链接地址http://www.linuxidc.com/Linux/2015-12/126740.htm

linux
相关资讯       Java HashSet  HashSet 
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款