HashSet是非同步的,允许使用null元素。如果多个线程同时访问一个Hashset,而其中至少一个线程修改了该set,那么它必须保持外部同步。这通常是通过对自然封装该set的对象执行同步操作来完成的。如果不存在这样的对象,则应该使用 Collections.synchronizedSet方法来“包装”set。最好在创建时完成这一操作,以防止对该set进行意外的不同步访问:
Set s = Collections.synchronizedSet(new HashSet(...));
在某些时候HashSet<Integer>的输出会恰好是有序的,这是因为插入HashSet的是Integer,其hashCode()实现就返回int值本身。所以在对象hashCode这一步引入了巧合的“按大小排序”。然后HashMap.hash(Object)获取了对象的hashCode()之后会尝试进一步混淆。所以在HashSet中,不保证有序与保证无序是不等价的。
// 代码实现
import java.util.HashSet;
import java.util.Iterator;
public class TestHashSet {
public static void main(String[] args) {
// TODO Auto-generated method stub
HashSet<Integer> set = new HashSet<>();
set.add(30000000);
set.add(50000000);
set.add(40000000);
set.add(10000000);
set.add(20000000);
// Java的HashSet是不保证有序,而与保证无序不等价
Iterator it = set.iterator();
while(it.hasNext()) {
System.out.print((Integer)it.next() + (it.hasNext() ? ", ": ""));
}
System.out.println();
for(Integer e : set) {
System.out.print(e + ", ");
}
System.out.println();
System.out.println("contains 10000000: " + set.contains(10000000));
}
参考资料:
Java 集合系列16之 HashSet详细介绍(源码解析)和使用示例
继续加油~