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());
        }
    }

}