Set集合我们在开发过程中一般情况下只用到HashSet这个实现类!
Set接口特点:存储的元素是无序的,不可重复的。
1.元素的无序性 != 随机性。真正的无序性,是指元素在底层存储的位置是无序的。2.不可重复性。当向Set集合中添加相同元素的时候,后面的这个添加不进去。而不会报错!
3.Set集合没有自己独有的方法,它的方法都是继承于Collection接口中的现有方法
4.HashSet类是非线程安全的
5.允许集合元素值为null
说明:引用对象在添加到Set集合中的时候,如何保证唯一性呢?要求:添加进Set集合中的对象所在的类必须重写equals()方法和hashCode()方法,进而保证Set集合中元素的不可重复性。
Set集合中的数据是如何存储的呢?使用了哈希算法!
当向Set中添加对象时,会先调用此对象所在类的hashCode()方法,计算此对象对应的哈希值,此哈希值决定了此对象在Set中的存储位置,如果此位置之前没有对象存储,则此对象直接存储在这个位置上。反之,如果此位置之前已经有对象存储,再通过equals()方法比较这两个对象是否相同,equals()方法返回true,说明为同一个对象,那么这个对象就不会被添加进来。
以上过程即为哈希算法!
注意:万一返回false,则两个对象都存储在此位置上(不建议如此!出现这种情况说明:你的hashCode()方法写的比较烂,把两个不同的对象返回了同一个哈希值!)
哈希算法的优点:如果采用普通equals()方法来判断存储数据的唯一性,那么当数据量非常大的时候,比如说,向set中添加第一万条数据,那么这条数据需要跟之前已经被添加到内存中的9999条数据依次进行比较,这个比较的过程所消耗的时间是巨大的,因此这种方法不可取。而哈希算法则是在数据添加进来前,就给数据算出来一个对应的哈希值,根据这个哈希值给出对应的位置去存储数据,不同的数据有不同的哈希值,也就是说每一个数据都有一个特定的位置去存储(数据在内存中存储的位置顺序是按照哈希值来的,而不是根据被添加进来的顺序存储的,所以导致了HashSet存储数据无序性的特点),在算数据对应的哈希值的时候,其实就是在对重复数据筛选的开始,(如果算出来的哈希值跟之前已经存储数据的哈希值有一样的,然后再用equals()方法去比较两个数据是否相同,是不是很节约时间又有效果。不过在此声明一点:如果你的hashCode()方法写的完美的话,哈希值一样,就代表着你的数据是完全一样的)这种做法大大提高存储数据的效率!
哈希算法因此而得名!
@Test
public void testHashSet() {
Set set = new HashSet();
set.add(123);
set.add("AA");
set.add("BB");
set.add(456);
set.add(null);//Set集合中允许元素值为null
/**
* 1.person类中只重写了equals()方法,那么1处返回true,但是p1和p2依旧会被添加到集合中
* 原因:2 处和3 处返回的哈希值不一样
* 2.person类中重写了equals()方法和hashCode()方法,1处返回true,5处p2添加不进去,但不会报错
* 原因:2 处和3 处返回的哈希值完全一样
*/
Person p1 = new Person("GG", 23);
Person p2 = new Person("GG", 23);
set.add(p1);//4
set.add(p2);//5
System.out.println(p1.equals(p2));//1
System.out.println(p1.hashCode());//2
System.out.println(p2.hashCode());//3
System.out.println(set.size());
System.out.println(set);
}
以上小例子能简单说明Set存储数据的依据和特点!不足之处希望大家多提宝贵建议!