day14--利用集合实现注册、登录/LinkedHashSet/TreeSet/Map集合

1、利用集合来实现注册、登录等功能。

包的命名:

              实体类:org.westos.entity  实体类:User

数据访问对象daoorg.westos.dao    注册、登录功能

              接口实现类:org.westos.dao.Impl

              测试类:org.westos.test  

  2Set集合和List集合的区别?

  Set集合:不允许元素重复,唯一(元素可以为null) ,不能保证迭代的顺序恒久不变(底层哈希表和hascode)无序(存储和取出不一致)

  List:允许元素重复,并且存储特点:有序(存储和取出一致)

 

Set存储元素时的唯一性:

HashSet集合的add方法底层依赖于双列集合HashMap,它依赖于两个方法,HashCode()方法和              equals()方法;先比较字符串的HashCode()码值一样,再比较equals()方法;如果hashCode码值一样,还要比较内容是否相同,由于存储String,String本身重写了equals()方法。但是在存储自定义对象时, 在Student类中并没重写这两个方法,解决,重写这两个方法,因此需要我们重写这两个方法。

Set.add()的原码分析:

class HashSet implements Set{
	private  HashMap<E,Object> map;
	
	//创建HashSet集合对象的时候,起始底层创建了一个HashMap集合对象
	 public HashSet() {
        map = new HashMap<>();
    }
    
    public boolean add(E e) {
        return map.put(e, PRESENT)==null;			//add方法底层依赖于HashMap集合的
    }
}

class HashMap<K,V> implements Map<K,V>{
		
		public V put(K key, V value) {
      	  return putVal(hash(key), key, value, false, true);
   		}
   	
   			//putVal方法
   		 final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
                
        Node<K,V>[] tab; Node<K,V> p; int n, i;	//Node是一种键值对对象
        
        //判断哈希表示是为空,如果为空.有set集合元素的情况,哈希表不为空
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
            Node<K,V> e; K k;			//k--->传入的元素
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))	
                						//一些判断,主要还是eqauls()方法
                e = p;	/e =p = key 
            else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            else {
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            
            if (e != null) { // existing mapping for key			mapping:映射	(Servlet  servlet-mapping)
                V oldValue = e.value;		//e.value=key ="hello"	,"world","java","world","java"
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;			//返回的oldValue:永远是第一次存储的哪个元素
            }
        }
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }
}
哈希方法
static final int hash(Object key) {	//传入的字符串元素		"hello","java","world" ,"hello"....
        int h;	//哈希码值 
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);	//无符号右移
        						底层依赖于第一个方法hashCode()							                                                计算机底层运算数据:补码
    }

Set<String> set = new HashSet<String>() ;

		set.add("hello") ;
		set.add("java") ;
		set.add("world");
		
		set.add("hello") ;
		set.add("java") ;
		set.add("world");

3、如果在开发中,元素唯一性,并且还要保证元素有序(存储和取出一致),使用LinkedHashSet集合

 LinkedHashSet集合:

  底层是一种链接列表和哈希表组成

  可以保证元素的唯一性,是由哈希表决定的(hashCode()equals())

  可以保证元素的迭代顺序一致(有序),存储和取出一致,是由链表决定

4TreeSet集合模拟情况下是通过自然顺序对集合中的元素排序

  TreeSet:

   可以保证元素唯一并且元素排序(Integer类型的元素自然升序)

   自然排序

   比较器排序

1)自然排序

treeSet存储自定义对象时,例如Student他不知道如何排序,所以自定义的类型必须实现Comparable,实现接口中的方法compareTo() :比较方法,重写方法

代码如下:

public int compareTo(Student s) {	//源码 cmp = k.compareTo(t.key),分析源码
//return 0;
		//按照某种规则,前提必须有这规则
		//主要条件:按照年龄从小到大
		int num  = this.age - s.age ; //如果年龄相等,不一定是同一个人
		//需要自己分析次要条件;
		//年龄相同,姓名的内容不一定相同,比较姓名
		int num2 = num==0 ? this.name.compareTo(s.getName()) : num ;
		return num2 ;
	}

(2)比较器排序

     Comparator保证集合中的元素进行比较器排序

3TreeSet集合的构造方式不同,使用的排序也不同

   自然排序:自定义的类实现Compareable接口,然后创建TreeSet对象,通过无参构造形式创建对象

   比较器排序 :public TreeSet(Comparator<E> comparator)

  两种方式:

  (1)自定义一个类,该类实现Comparator接口,重写Comparator接口中的compare()方法

  (2)直接使用接口匿名内部类的方式实现

 

 TreeSet集合保证元素唯一,是看返回值是否为0

  保证元素进行排序,两种排序方式

 使用比较器排序的方式去,遍历Student对象,并且按照姓名长度进行比较

5、Map集合:键值的映射关系的一种集合(接口)

  将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。

  Map<K,V> ,Map集合中,只针对键有效,跟值无关 Map接口的子实现类:HashMapTreeMap

   面试题:

   Map集合和Collection的区别?

   Map集合:是一种键和值的映射关系(双列集合) 当作为:夫妻对

   Collection集合:单列集合,只能存储一种类型的元素,当作为:光棍

   间接关系:HashSet依赖于Map接口的子实现类HashMap

      TreeSet依赖于Map接口的子实现类TreeMap

  

 Map接口的功能:

       V put(K key,V value) :添加功能:将指定的值和键关联起来

   如果当前的这个键是一次存储,则返回值null

   如果不是第一次存储,返回值是第一次对应的值,当前的值就把之前的键对应的值替换掉!

 

  获取功能

   Set<Map.Entry<K,V>> entrySet() :Map集合的遍历有关系(键值对对象)

   Set<K> keySet():获取映射关系中所有的键的集合

   int size()返回此映射中的键-值映射关系数

   删除功能

   void clear():删除所有映射关系

        Vremove(Object key)如果存在一个键的映射关系,则将其从此映射中移除

   

    判断功能:

     boolean containsKey(Object key)如果此映射包含指定键的映射关系,则返回 true

   boolean containsValue(Object value):映射关系中是否包含指定的值

   boolean isEmpty():判断映射关系是否为空

   Map的两种遍历:

   1)这种遍历方式实际开发中经常用的...

     Set<K> keySet():获取映射关系中所有的键的集合

     V get(Object key):通过键找值

  转换法:

   1)将所有的丈夫集中起来

   2)让丈夫它对应的妻子

   3)将他们遍历出来  

   2Map集合的另一种方式的遍历 Set<Map.Entry<K,V>> entrySet() :Map集合的遍历有关系(键值对对象)

  转化法: 1)获取所有的结婚证 2)通过结婚证分别找对应的丈夫和妻子 3)遍历输出

  思路: 1)获取所有的键值对象entrySet()

        2) K getKey() v getValue(),获取键值对对象中的每个键和每个值

        3)遍历   

猜你喜欢

转载自blog.csdn.net/liuxiaofan_/article/details/80257061