歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

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對應不上,所以才會有上述的問題。

Copyright © Linux教程網 All Rights Reserved