疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

HashSet的初步了解


 

   

  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方法修改一下:

  [java] view plaincopyprint?

  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、这样我们可以减少比较次数、从而提高效率。