package java1; import org.junit.Test; import java.lang.annotation.Target; import java.util.*; /** * 1.Set接口的框架结构 * \------Collection接口:单列集合,用来存储一个一个对象(对于基本类型可以以包装类的形式去存储) * * \----Set接口:无序,不可重复。---> * * \----HashSet:作为Set接口的主要实现类:线程不安全的,可以存储null值。 * \----LinkedHashSet:作为HashSet的子类;遍历其内部数据时可以按照添加的顺序遍历。 * \----TreeSet:可以按照添加对象指定属性,进行排序。 * 1.Set接口中没有额外定义新的方法,都是Collection中声明过的方法。 * 2.要求:向Set中添加到数据,其所在的类一定要重写hashCode方法和equals * 要求:重写的hashcode和equals尽肯能保持一致性 :相等的对象必须要有相等的散列码(哈希值)--equals相等,哈希值一定相等。 * @author 冀帅 * @date 2020/8/11-10:33 */ public class SetTest { /* * 一丶Set:存储无序的,不可重复的 * 以HashSet为例: * 1.无序性:不等于随机性。存储的数据在底层数组中并非按照数组索引的顺序添加。 * 而是根据数据的哈希值决定的。 * * * * 2.不可重复性:保证添加的元素按照equals()方法判断时,不返回true,即:相同的元素只能添加一个。 * (hashcode相等equals不一定相等 * equals相等hashcode一定相等 * 所以:先判断hashcode 要是hashcode都不相等。那equals一定不相等) * * * * * 二丶添加元素的过程:以HashSet为例: * 我们想HashSet中添加元素a,首先调用元素a所在类的hashcode(方法,计算元素a的hash值, * 此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置(即为:索引位置), * 判断数组此位置上是否已经有元素: * 如果此位置上没有其他元素,在元素a添加成功 * 如果有其他元素b(或者已经存在以链表形式存在的多个元素),则比较元素a与元素b的哈希值: * 如果hash值不同,则添加成功。---情况2 * 如果hash值相同,则比较equals * equals相同,失败 * equals不同,成功---情况3 * 总结:位置-hashcode-equals * * 对于添加成功的情况2和情况3:元素a与已经存在指定索引位置上数据以链表的方式存储 * jdk 7:元素a(新的元素)放到数组中,只想原来的元素 * jdk 8 :原来的元素在数组中,指向元素a(新的元素) * 7上8下(新的元素) * HashSet底层:数组+链表 * * */ @Test public void test1(){ Set set = new HashSet(); set.add(456); set.add(123); set.add("AA"); set.add(129); set.add("CC"); set.add(new User("Tom",12)); set.add(new User("Tom",12));// Iterator iterator = set.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } } }