重踏学习Java路上_Day17(登录注册案例,Set集合,Collection集合总结,在集合中常见的数据结构)

1:登录注册案例(理解)

需求:用户登录注册案例。

按照如下的操作,可以让我们更符号面向对象思想
    A:有哪些类呢?
    B:每个类有哪些东西呢?
    C:类与类之间的关系是什么呢?
    
分析:
    A:有哪些类呢?
        用户类
        测试类
    B:每个类有哪些东西呢?
        用户类:
            成员变量:用户名,密码
            构造方法:无参构造
            成员方法:getXxx()/setXxx()
                       登录,注册
                       
            假如用户类的内容比较对,将来维护起来就比较麻烦,为了更清晰的分类,我们就把用户又划分成了两类
                用户基本描述类
                    成员变量:用户名,密码
                    构造方法:无参构造
                    成员方法:getXxx()/setXxx()
                用户操作类
                    登录,注册
        测试类:
            main方法。
    C:类与类之间的关系是什么呢?
        在测试类中创建用户操作类和用户基本描述类的对象,并使用其功能。
        
分包:
    A:功能划分
    B:模块划分
    C:先按模块划分,再按功能划分
    
今天我们选择按照功能划分:
    用户基本描述类包 cn.itcast.pojo
    用户操作接口 cn.itcast.dao
    用户操作类包 cn.itcast.dao.impl
        今天是集合实现,过几天是IO实现,再过几天是GUI实现,就业班我们就是数据库实现
    用户测试类 cn.itcast.test

2:Set集合(理解)
    (1)Set集合的特点
        无序,唯一   (一个不包含重复元素的 collection。因为无序,所以没有索引,所以没有get(index)方法,只有list接口才有get(index))
    (2)HashSet集合(掌握)
        A:底层数据结构是哈希表(是一个元素为链表的数组)
        B:哈希表底层依赖两个方法:hashCode()和equals(),哈希表保证了元素的唯一性
          执行顺序:
            首先比较哈希值是否相同
                相同:继续执行equals()方法
                    返回true:元素重复了,不添加
                    返回false:直接把元素添加到集合
                不同:就直接把元素添加到集合
        C:如何保证元素唯一性的呢?
            由hashCode()和equals()保证的
        D:开发的时候,重写hashCode()与equal()代码非常的简单,自动生成即可。(如果是自己重写代码,一般是返回值=基本类型*特别值+引用类型的.hashCode(),这样生成)
        E:HashSet的子类:LinkedHashSet<E> , 特点:具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现,此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。本子类没有任何特有方法,继承自HashSet所有方法,所以可以直接用父类任何方法。哈希表保证唯一性,链表保证有序性。
        F:HashSet存储字符串并遍历 :除了不能用普通for方法,其他一样,因为set无序没有get()方法,所以不能有普通for,只能用增强for,与Iterator
        G:HashSet存储自定义对象并遍历(对象的成员变量值相同即为同一个元素) 重写equal与hashcode方法
       
    (3)TreeSet集合
        A:底层数据结构是红黑树(是一个自平衡的二叉树),TreeMap;
        B:保证元素的排序方式
            a:自然排序(元素具备比较性)
                让元素所属的类实现Comparable接口
            b:比较器排序(集合具备比较性)
                让集合构造方法接收Comparator的实现类对象
        C:把我们讲过的代码看一遍即可
    (4)案例:(代码在随笔名称:TreeSet概述(源码和内部图 进行解析)
        A:获取无重复的随机数
        B:键盘录入学生按照总分从高到底输出

-------------------------------------------------------------------------------------------------------

/*
 * HashSet:存储字符串并遍历
 * 问题:为什么存储字符串的时候,字符串内容相同的只存储了一个呢?
 * 通过查看add方法的源码,我们知道这个方法底层依赖 两个方法:hashCode()和equals()。
 * 步骤:
 *         首先比较哈希值
 *         如果相同,继续走,比较地址值或者走equals()
 *         如果不同,就直接添加到集合中    
 * 按照方法的步骤来说:    
 *         先看hashCode()值是否相同
 *             相同:继续走equals()方法
 *                 返回true:    说明元素重复,就不添加
 *                 返回false:说明元素不重复,就添加到集合
 *             不同:就直接把元素添加到集合
 * 如果类没有重写这两个方法,默认使用的Object()。一般来说不同相同。
 * 而String类重写了hashCode()和equals()方法,所以,它就可以把内容相同的字符串去掉。只留下一个。
 */

HashSet add()方法源码解析:用于理解为什么set接口只允许唯一元素进入Set,而不能重复元素
interface Collection {
    ...
}

interface Set extends Collection {
    ...
}

class HashSet implements Set {
    private static final Object PRESENT = new Object();
    private transient HashMap<E,Object> map;
    
    public HashSet() {
        map = new HashMap<>();
    }
    
    public boolean add(E e) { //e=hello,world
        return map.put(e, PRESENT)==null;
    }
}

class HashMap implements Map {
    public V put(K key, V value) { //key=e=hello,world
    
        //看哈希表是否为空,如果空,就开辟空间
        if (table == EMPTY_TABLE) {
            inflateTable(threshold);
        }
        
        //判断对象是否为null
        if (key == null)
            return putForNullKey(value);
        
        int hash = hash(key); //和对象的hashCode()方法相关
        
        //在哈希表中查找hash值
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            //这次的e其实是第一次的world
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
                //走这里其实是没有添加元素
            }
        }

        modCount++;
        addEntry(hash, key, value, i); //把元素添加
        return null;
    }
    
    transient int hashSeed = 0;
    
    final int hash(Object k) { //k=key=e=hello,
        int h = hashSeed;
        if (0 != h && k instanceof String) {
            return sun.misc.Hashing.stringHash32((String) k);
        }

        h ^= k.hashCode(); //这里调用的是对象的hashCode()方法

        // This function ensures that hashCodes that differ only by
        // constant multiples at each bit position have a bounded
        // number of collisions (approximately 8 at default load factor).
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }
}
hs.add("hello");
hs.add("world");
hs.add("java");
hs.add("world");
-------------------------------------------------------------------------------------------------------

HashSet子类:LinkedHashSet

/*
 * LinkedHashSet:底层数据结构由哈希表和链表组成。
 * 哈希表保证元素的唯一性。
 * 链表保证元素有素。(存储和取出是一致)
 */
public class LinkedHashSetDemo {
    public static void main(String[] args) {
        // 创建集合对象
        LinkedHashSet<String> hs = new LinkedHashSet<String>();

        // 创建并添加元素
        hs.add("hello");
        hs.add("world");
        hs.add("java");
        hs.add("world");
        hs.add("java");

        // 遍历
        for (String s : hs) {
            System.out.println(s);
        }
    }
}
--------------------------------------------------------------------------------------------------------       
3:Collection集合总结(掌握)
    Collection
        |--List    有序(存储顺序与读取数据顺序不一致),可重复
            |--ArrayList
                底层数据结构是数组,查询快,增删慢。
                线程不安全,效率高
            |--Vector
                底层数据结构是数组,查询快,增删慢。
                线程安全,效率低
            |--LinkedList
                底层数据结构是链表,查询慢,增删快。
                线程不安全,效率高
        |--Set    无序,唯一
            |--HashSet
                底层数据结构是哈希表。
                如何保证元素唯一性的呢?
                    依赖两个方法:hashCode()和equals()
                    开发中自动生成这两个方法即可
                |--LinkedHashSet
                    底层数据结构是链表和哈希表
                    由链表保证元素有序
                    由哈希表保证元素唯一
            |--TreeSet
                底层数据结构是红黑树。
                如何保证元素排序的呢?
                    自然排序
                    比较器排序
                如何保证元素唯一性的呢?
                    根据比较的返回值是否是0来决定
                    
4:针对Collection集合我们到底使用谁呢?(掌握)
    唯一吗?
        是:Set
            排序吗?
                是:TreeSet
                否:HashSet
        如果你知道是Set,但是不知道是哪个Set,就用HashSet。
            
        否:List
            要安全吗?
                是:Vector
                否:ArrayList或者LinkedList
                    查询多:ArrayList
                    增删多:LinkedList
        如果你知道是List,但是不知道是哪个List,就用ArrayList。
    
    如果你知道是Collection集合,但是不知道使用谁,就用ArrayList。
    
    如果你知道用集合,就用ArrayList。
    
5:在集合中常见的数据结构(掌握)
    ArrayXxx:底层数据结构是数组,查询快,增删慢
    LinkedXxx:底层数据结构是链表,查询慢,增删快
    HashXxx:底层数据结构是哈希表。依赖两个方法:hashCode()和equals()
    TreeXxx:底层数据结构是二叉树。两种方式排序:自然排序和比较器排序

6.ArrayList集合的toString()方法源码解析
代码:
    Collection c = new ArrayList();
    c.add("hello");
    c.add("world");
    c.add("java");
    
    System.out.println(c);
    
为什么c输出的不是地址值呢?

java.util
类 ArrayList<E>
java.lang.Object
  java.util.AbstractCollection<E>   -----------------这里才有toString()的实现方法
      java.util.AbstractList<E>     ----------------- 这里也没有
          java.util.ArrayList<E>    ---------------- 这里没有

    A:Collection c = new ArrayList();
        这是多态,所以输出c的toString()方法,其实是输出ArrayList的toString()
    B:看ArrayList的toString()
        而我们在ArrayList里面却没有发现toString()。
        以后遇到这种情况,也不要担心,你认为有,它却没有,就应该去它父亲里面看看。
    C:toString()的方法源码
    
        public String toString() {
            Iterator<E> it = iterator(); //集合本身调用迭代器方法,得到集合迭代器
            if (! it.hasNext())
                return "[]";
    
            StringBuilder sb = new StringBuilder();
            sb.append('[');
            for (;;) {
                E e = it.next(); //e=hello,world,java
                sb.append(e == this ? "(this Collection)" : e);
                if (! it.hasNext())
                    //[hello, world, java]
                    return sb.append(']').toString();
                sb.append(',').append(' ');
            }
        }
       

原文地址:https://www.cnblogs.com/canceler/p/4620724.html