Set 的主要实现类:HashSet
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Set 的主要实现类:HashSet相关的知识,希望对你有一定的参考价值。
- Set 可以存null
- Set 下的方法基本上就是 Collection 中的
- Set 的“无序性” ≠ “随机性”:“无序性”是指元素在内存中存储的位置是无序的,但是位置是确定的,并不会变化
- Set 是不可重复的(使用哈希算法存储)
关于以上几点的说明:
public class TestSet {
@Test
public void TestHashSet() {
Set set1 = new HashSet();
set1.add(null);// 可以存null
set1.add(1);
set1.add(2);
set1.add(new String("A"));
set1.add(new String("A"));// 不可重复性(依赖于 equals()和 hashCode()方法)
set1.add("B");
System.out.println(set1);// [null, 1, A, 2, B]
Set set2 = new HashSet();
set2.add(2);
set2.add(null);
set2.add("B");
set2.add(1);
set2.add("A");
System.out.println(set2);// [null, 1, A, 2, B],无序性
}
}
关于不可重复性的进一步说明:
对象存储可视为先调用 hashCode()方法,若当前的哈希值对应的内存位置已经有对象了(已存在与当前方法调用者的哈希值相同的对象),则再比较 equals()方法,而且要求此时的 equals()方法也必须返回 true ,若返回 false 则都存储(不建议如此)。
事实上,我们要求 hashCode()方法能够在使用 equals()方法比较对象返回 false 的情况下算出不同的哈希值,如果出现 equals()方法返回 false 而算出相同的哈希值的情况,说明该 hashCode()方法设计的不好。
另外,两个实际相同的对象也不应算出不一样的哈希值(此时Set中会有实际上的“重复”的元素),这同样需要避免。
如下代码说明了这一问题:
public class TestSet2 {
public static void main() {
Set set = new HashSet();
set.add(new Person1("aa"));
set.add(new Person1("aa"));
set.add(new Person2("aa"));
set.add(new Person2("aa"));// Person2 没有重写 hashCode()方法,此时调用的是 Object类定义的hashCode()方法,算出哈希值不一样,所以可以存储
System.out.println(set);// [Person2 [name=aa], Person2 [name=aa],Person1 [name=aa]]
}
}
class Person1 {
private String name;
@Override
public String toString() {
return "Person1 [name=" + name + "]";
}
public Person1(String name) {
super();
this.name = name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person1 other = (Person1) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
class Person2 {
private String name;
public Person2(String name) {
super();
this.name = name;
}
@Override
public String toString() {
return "Person2 [name=" + name + "]";
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person2 other = (Person2) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
总之,我们应要求 hashCode()方法与 equals()方法一致,直接用 eclipse 重写就行:。
关于Set的底层存储:
先调用 hashCode()方法,若哈希值不一样,则存储,若一样,则调用 equals()方法比较,若返回 true 不存储,返回 false 则存储(应避免)。
以上是关于Set 的主要实现类:HashSet的主要内容,如果未能解决你的问题,请参考以下文章