标签:
HashSet是无序的、它在添加元素的时候、是无序的、输出的时候、而不是依据你所添加元素的顺序而打印出来。
import java.util.*; public class HashSetDemo { public static void main(String[] args) { HashSet hs = new HashSet(); Add(hs); System.out.println(hs); } public static void Add(HashSet hs) { for (int i = 1;i < 10; i++) { hs.add("java0" + i); } } }
[java04, java05, java02, java03, java01, java08, java09, java06, java07]
这是特点之一,其二就是它在底层可以自动去除重复的元素、
import java.util.*; public class HashSetDemo { public static void main(String[] args) { HashSet hs = new HashSet(); Add(hs); System.out.println(hs); } public static void Add(HashSet hs) { hs.add("java01"); hs.add("java02"); hs.add("java01"); hs.add("java03"); hs.add("java01"); hs.add("java03"); } }
[java02, java03, java01]
但是如果添加的是对象而不是单一元素呢?
我们来试试、
import java.util.*; public class HashSetDemo { public static void main(String[] args) { HashSet hs = new HashSet(); Add(hs); show(hs); } public static void Add(HashSet hs) { hs.add(new Person("lisi01", 22)); hs.add(new Person("lisi02", 37)); hs.add(new Person("lisi01", 22)); hs.add(new Person("lisi03", 41)); } public static void show(HashSet hs) { for (Iterator it = hs.iterator(); it.hasNext() ; ) { Person p = (Person)it.next(); sop(p.getName() + "->" + p.getAge()); } } public static void sop(Object obj) { System.out.println(obj); } } class Person { private String name; private int age; Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } }
lisi03->41
lisi01->22
lisi01->22
lisi02->37
我们可以发现、 里面有重复元素的存在、 HashSet它底层并没有为我们去除重复元素。为什么呢?
原因如下:
1:HashSet底层先调用了hashCode方法、当哈希值相同时再调用equals方法进行比较、但是系统不知道我们比较的标准、
所以我们要重写equals方法和hashCode方法。
import java.util.*; public class HashSetDemo { public static void main(String[] args) { HashSet hs = new HashSet(); Add(hs); show(hs); } public static void Add(HashSet hs) { hs.add(new Person("lisi01", 22)); hs.add(new Person("lisi02", 37)); hs.add(new Person("lisi01", 22)); hs.add(new Person("lisi03", 41)); } public static void show(HashSet hs) { for (Iterator it = hs.iterator(); it.hasNext() ; ) { Person p = (Person)it.next(); sop(p.getName() + "->" + p.getAge()); } } public static void sop(Object obj) { System.out.println(obj); } } class Person { private String name; private int age; Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } public int hashCode() { return 1; } public boolean equals(Object obj) { if (!(obj instanceof Person)) return false; Person p = (Person)obj; return this.name.equals(p.name) && this.age == p.age; } }
lisi03->41
lisi02->37
lisi01->22
这样我们就可以进行去重了、先调用HashCode、复写方法、返回1,这样就调用equals方法来进行我们所需要的比较标准了。
其实为了提高效率、我们可以让它们有独立的哈希值、这样就可以避免进行无谓的比较了。
在这之前我们来测试一下、 是否真的是调用了hashCode和equals方法、我们可以把那段代码修改一下:
public int hashCode() { System.out.println(this.name + "....HashCode"); return 1; } public boolean equals(Object obj) { if (!(obj instanceof Person)) return false; Person p = (Person)obj; System.out.println(this.name + "....equals...." + p.name); return this.name.equals(p.name) && this.age == p.age; }
lisi01....HashCode
lisi02....HashCode
lisi02....equals....lisi01
lisi01....HashCode
lisi01....equals....lisi02
lisi01....equals....lisi01
lisi03....HashCode
lisi03....equals....lisi02
lisi03....equals....lisi01
lisi03->41
lisi02->37
lisi01->22
从上面的结果得知、 是先计算哈希值、如果相同就调用equals、 反之则不调用。 那么我们可以依据这个来改进一下、
只需要把hashCode方法修改一下:
public int hashCode() { System.out.println(this.name + "....HashCode"); return this.name.hashCode() + age*19; }
lisi01....HashCode
lisi02....HashCode
lisi01....HashCode
lisi01....equals....lisi01
lisi03....HashCode
lisi03->41
lisi02->37
lisi01->22
依据这个我们可以更加肯定、 当哈希值相同的时候,不再调用equals方法,当不同时,就调用equals、这样我们可以减少比较次数、从而提高效率。
记录一下。。2015年6月2日
标签:
原文地址:http://blog.csdn.net/acm_th/article/details/46322999