package com.test1; import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class SetTest { public static void main(String[] args) { /* * Set<String> set = new HashSet<>(); * System.out.println(set.add("abc")); * System.out.println(set.add("xyz")); * System.out.println(set.add("abc")); * * for (Iterator<String> it = set.iterator(); it.hasNext();) { * System.out.println(it.next()); } */ /* * String a = "abc"; String b = "abc"; System.out.println(a.hashCode()); * System.out.println(b.hashCode()); */ Set<People> set2 = new HashSet<>(); set2.add(new People("zhangsan")); set2.add(new People("lisi")); set2.add(new People("zhangsan")); for (Iterator<People> it = set2.iterator(); it.hasNext();) { System.out.println(it.next().getName()); } } } class People { String name; public People(String name) { this.name = name; } public String getName() { return this.name; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof People) { People people = (People) obj; if(this.name.equals(people.getName())); return true; } return false; } @Override public int hashCode() { return this.name.hashCode(); } }
我们来看HashSet的构造方法:
/** * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has * default initial capacity (16) and load factor (0.75). */ public HashSet() { map = new HashMap<>(); }
竟然是new HashMap<>();
关于HashSet与HashMap之间的关系:
HashSet是由HashMap来实现的。HashSet里面的几乎所有的方法都是由HashMap实现的
这个HashMap的key就是放进HashSet中的对象,value就是一个Object类型的对象,当调用HashSet的add方法时,实际上是向HashMap中增加了一行(key-value对),该key就是向HashSet中增加的那个对象,该行的value就是一个Object类型的对象。HashMap底层采用数组维护(数组中每个元素都是一个Map.Entry对象),调用增加的那个对象的hashCode方法,得到一个hashCode值,然后根据该值计算出一个数组的下标索引(计算出数组中的一个位置),将准备添加到Map中的对象与该位置处的对象进行比较(equals方法),如果相同,那么就向该位置处的那个对象(Map.Entry类型)的value值替换掉,否则沿着该Entry链继续重复上述过程,如果链的最后依然没有找到相同的对象,那么这个时候就将该对象添加到数组中,将数组中该位置处的Entry对象链接到这个对象后面:对于HashSet与HashMap来说,这样做是为了提高查找的效率,使得查找时间不随着Set或Map的大小而改变。
查看add方法
/** * Adds the specified element to this set if it is not already present. * More formally, adds the specified element <tt>e</tt> to this set if * this set contains no element <tt>e2</tt> such that * <tt>(e==null ? e2==null : e.equals(e2))</tt>. * If this set already contains the element, the call leaves the set * unchanged and returns <tt>false</tt>. * * @param e element to be added to this set * @return <tt>true</tt> if this set did not already contain the specified * element */ public boolean add(E e) { return map.put(e, PRESENT)==null; }