Set接口与List接口不同,Set接口中不能加入重复的元素。
以 HashSet为例:
1)先以String为HashSet存放的类型为例:
import java.util.HashSet;
import java.util.Set;
public class TestHashSet {
public static void main(String args[]){
Set<String> set=new HashSet<String>();
set.add("abc");
set.add("def");
set.add("qqcc");
set.add("abc");
System.out.println(set);
}
}
结果为:
[abc, def, qqcc]
从结果容易发现,确实没有出现重复的元素。
到底是通过什么来判断元素是否相同呢?
下面我们再来看一个以自定义类的对象为HashSet存放的类型。
import java.util.HashSet;
import java.util.Set;
class Animal{
private String style;
private String color;
public Animal(String style, String color) {
super();
this.style = style;
this.color = color;
}
public String toString() {
return "Animal [color=" + color + ", style=" + style + "]";
}
}
public class TestHashSet {
public static void main(String args[]){
Set<Animal> set=new HashSet<Animal>();
set.add(new Animal("dog", "yellow"));
set.add(new Animal("cat", "black"));
set.add(new Animal("bird","white"));
set.add(new Animal("cat", "black"));
System.out.println(set);
}
}
结果是:
[Animal [color=black, style=cat], Animal [color=black, style=cat], Animal [color=white, style=bird], Animal [color=yellow, style=dog]]
“黑猫”这个对象重复了,即此时没有像Set接口规定的那样是不允许有重复的元素。
其实,Set接口中,是通过hashCode(),与equals()两个方法来判断是否是相同的元素。
在String类中,它重写了Object类的hashCode(),与equals()两个方法。见下图:
String 类的hashCode()方法:
public int hashCode() {
int h = hash;
if (h == 0) {
int off = offset;
char val[] = value;
int len = count;
for (int i = 0; i < len; i++) {
h = 31*h + val[off++];
}
hash = h;
}
return h;
}
String类的equals()方法:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
从两个方法代码可以看出,只要两个字符串相等,它们即可认为是相等元素。
所以在以自定义类的对象为HashSet存放的类型,我们也应该覆写Object类的hashCode(),与equals()两个方法。这样Set接口才能判断出是否重复元素。看下面代码:
import java.util.HashSet;
import java.util.Set;
class Animal{
private String style;
private String color;
public Animal(String style, String color) {
super();
this.style = style;
this.color = color;
}
public String toString() {
return "Animal [color=" + color + ", style=" + style + "]";
}
public int hashCode(){
return this.style.hashCode()*this.color.hashCode();
}
public boolean equals(Object obj){
if(this==obj){
return true;
}
if(!(obj instanceof Animal)){
return false;
}
Animal animal=(Animal)obj;
if(this.style.equals(animal.style)&&this.color.equals(animal.color)){
return true;
}else{
return false;
}
}
}
public class TestHashSet {
public static void main(String args[]){
Set<Animal> set=new HashSet<Animal>();
set.add(new Animal("dog", "yellow"));
set.add(new Animal("cat", "black"));
set.add(new Animal("bird","white"));
set.add(new Animal("cat", "black"));
System.out.println(set);
}
}
结果是:
[Animal [color=black, style=cat], Animal [color=white, style=bird], Animal [color=yellow, style=dog]]
从结果可以看出,覆写了Object()的equals()和hashCode()两个方法后,结果出现的就没有了重复的元素了。
所以Set接口是通过hashCode(),与equals()来判断两个元素是否相等的。