Set最常见子类HashSet

来源:互联网 发布:卢比奥生涯数据 编辑:程序博客网 时间:2024/06/05 19:30

一 HashSet概述

HashSet是Set接口的典型实现,大多时候使用Set集合时就是使用这个实现类。HashSet按Hash算法来存储集合中的元素,因此具有很好的存取和查找性能。
当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据该HashCode值来决定该对象在HashSet中存储位置。如果有两个元素通过equals方法比较返回true,但它们的hashCode()方法返回值不相等,HashSet将会把它们存储在不同位置,也就可以添加成功。也就是说,HashSet集合判断两个元素相等的标准是通过equals()方法比较相等、并且两个对象的hashCode()方法的返回值也相等。

 

二 HashSet具有以下特点

  • 不能保证元素的排列顺序,顺序可能与元素的添加顺序不同,元素的顺序可能变化。
  • HashSet不是同步的,如果多个线程同时访问一个HashSet,如果有2条或者2条以上线程同时修改了HashSet集合时,必须通过代码来保证其同步。
  • 集合元素值可以是null。

三 HashSet无重复性应用

1 代码示例

import java.util.*;// 类A的equals方法总是返回true,但没有重写其hashCode()方法class A{public boolean equals(Object obj){return true;}}// 类B的hashCode()方法总是返回1,但没有重写其equals()方法class B{public int hashCode(){return 1;}}// 类C的hashCode()方法总是返回2,且重写其equals()方法总是返回trueclass C{public int hashCode(){return 2;}public boolean equals(Object obj){return true;}}public class HashSetTest{public static void main(String[] args){HashSet books = new HashSet();// 分别向books集合中添加两个A对象,两个B对象,两个C对象books.add(new A());books.add(new A());books.add(new B());books.add(new B());books.add(new C());books.add(new C());System.out.println(books);}}

2 运行结果

[B@1, B@1, C@2, A@1db9742, A@106d69c]

3 代码说明

上面代码中向books集合中分别添加了两个A对象,两个B对,两个C对象,其中C类重写equals()方法总是返回true,hashCode()方法总是返回2,这将导致HashSet把两个C对象当成同一个对象。注意:如果需要把某个类的对象保存到HashSet集合中,重写这个类的equals()方法和hashCode()方法时,应该尽量保证两个对象通过equals()方法比较返回true时,他们的hashCode()方法返回值也相等。

 四 HashSet混乱示例

1 代码示例

import java.util.*;class R{int count;public R(int count){this.count = count;}public String toString(){return "R[count:" + count + "]";}public boolean equals(Object obj){if(this == obj)return true;if (obj != null && obj.getClass() == R.class){R r = (R)obj;return this.count == r.count;}return false;}public int hashCode(){return this.count;}}public class HashSetTest2{public static void main(String[] args){HashSet hs = new HashSet();hs.add(new R(5));hs.add(new R(-3));hs.add(new R(9));hs.add(new R(-2));// 打印HashSet集合,集合元素没有重复System.out.println(hs);// 取出第一个元素Iterator it = hs.iterator();R first = (R)it.next();// 为第一个元素的count实例变量赋值first.count = -3;     // ①// 再次输出HashSet集合,集合元素有重复元素System.out.println(hs);// 删除count为-3的R对象hs.remove(new R(-3));    // ②// 可以看到被删除了一个R元素System.out.println(hs);System.out.println("hs是否包含count为-3的R对象?"+ hs.contains(new R(-3))); // 输出falseSystem.out.println("hs是否包含count为-2的R对象?"+ hs.contains(new R(-2))); // 输出false}}

 2 运行结果

[R[count:-2], R[count:-3], R[count:5], R[count:9]]
[R[count:-3], R[count:-3], R[count:5], R[count:9]]
[R[count:-3], R[count:5], R[count:9]]
hs是否包含count为-3的R对象?false
hs是否包含count为-2的R对象?false

3 代码说明

当程序把可变成员变量加入到HashSet中之后,尽量不要去修改该集合元素中参与计算hashCode()、equals()变量,否则将会导致HashSet无法正确操作这些集合元素。

0 0
原创粉丝点击