JAVASE23天从入门到精通_Day15

双列集合简介
双列集合 : 由两根单列集合组成的集合叫双列集合

双列集合的别称 : 键值对集合,映射集合,夫妻对集合
	左边的集合: 键集
	右边的集合: 值集
	映射关系 : 键隐射到值 (username -- password)
    夫妻对集合 : 一妻多夫
		丈夫 :-> 唯一
		妻子 :-> 重复
			"奶量" -- "露露"
            "Pone" -- "露露"

双列集合具备:
	1. 长度可变
	2. 只能存对象(基本数据类型元素存储解决方案: 包装类)
    3. 键集集合中的元素 唯一
    4. 值集集合中的元素 可以重复
    5. 元素存取无序 -> 键集是无序的 - "夫唱妇随"

在这里插入图片描述

双列集合的体系结构

在这里插入图片描述

Map<K,V>
Map<K,V> : 接口  -> 根节点

创建容器:
	Map<K,V> 集合 = new 具体子类对象<K,V>();
		//Map<K,V> 集合 = new HashMap<K,V>();
		//Map<K,V> 集合 = new TreeMap<K,V>();
	格式解释:
		<K,V> : 因为是双列集合,键和值的元素类型都需要指定
			具体使用的时候,2个引用数据类型的类名去替换K,V即可
				K : 键集元素的数据类型 V : 值集元素的元素类型
增删改查:/:  V put(K key, V value) : 往集合中添加一对隐射关系
		//如果键不存在,添加元素成功,返回null
		//如果键存在,修改该键所对于的值,返回oldValue
	-> 通过分析源码咱们得知 : Map集合中运行有null,但只能有一个null键
	
	删 :
		V remove(Object key) : 根据传入的键删除集合中的一对隐射关系,并把删除的值返回 
 	    boolean remove(K key,V value): 根据传入的键值对删除集合中的这对映射关系,返回删除是否成功
 	    void clear()  : 清空集合中所有的键值对关系
 	    
 	查 :
		V get(Object key) : 根据传入的键返回其对应的值 -> 丈夫找妻子
		int size() : 返回集合中有几对元素
		
		Set<K> keySet() : 获取双列集合中所有的键元素,并存入到Set集合 -> 获取键集 -> 召集所有的丈夫
		Collection<V> values()  : 获取双列集合中所有的键元素,并存入到Collection(元素可重复的)集合 -> 获取值集 -> 召集所有的妻子
		
		boolean isEmpty(): 查询集合是否为空
        boolean containsKey(Object key) : 判断集合是否包含传入的键
 		boolean containsValue(Object value) : 判断集合是否包含传入的值  
 
遍历:
	1. 面向过程的方式 (先召集所有的丈夫,再丈夫找媳妇)
        	a. Set<K> keySet()
        	b. 遍历存有丈夫的集合
        	c. 在遍历中 获取丈夫对于的妻子V get(Object key) 
    2. 面向对象的方式 (召集所有的结婚证对象,再通过结婚证对象获取结婚证对象上的丈夫和妻子)
        	a. 召集所有的结婚证对象 : Set<Map.Entry<K,V>> entrySet()  
                	Map.Entry<K,V> 
                		Map.Entry : Entry接口是Map接口中的内部接口
                		Entry<K,V> : Entry类型中封装着键和值
                		Map.Entry<K,V>  : 是存储Entry对象Set集合的泛型
            b. 遍历存储结婚证对象的Set集合,取出每一本Entry对象
            c. 通过每一个 Entry对象 获取 其封装的键和值
            	Entry接口中:
					K getKey()
                    V getValue()
HashMap<K,V>
底层为Hash表的Map接口实现:
	创建对象
	增删改查
	遍历
	//和Map接口一模一样
HashMap<K,V>的底层原理
JavaHash算法去重原理 :
	比较2个对象的hash值 && (比较2个对象的地址值 || 新元素.equals(老元素))
    this.hashCode() == o.hashCode()  && (this == o this.equals(o))  
     //冲洗hashCode和equals 方法的意义在于 想让集合按照对象属性值去重而不是对象的地址值去重
        
当存放第1024个元素时,HashMap集合底层数组的长度是多少 (不考虑特殊情况)?  2048
      1. 当创建一个HashMap集合,源码会在底层创建一个容量为16的数组, 这个数组的加载因子是 0.75
      		//构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空 HashMap。
        	加载因子 : 底层数组扩容的时机
      2. 当添加的元素达到加载因子的条件时,底层数组会进行扩容,扩容2;
	  3. 当集合底层数组容量翻倍后,原来在集合中的元素和要添加的元素重新计算应该存放的索引位置
	  -------------------------------------------------------------------
	  4. 当添加的元素在底层hash表所对应的索引位置值是 null 的时候, 就算达到了加载因子的条件也不扩容
	  5.JDK8的时候,哈希表底层实现由数组+链表升级为数组+链表+红黑树! 
          	当链表中元素挂载的数量>=8的时候,会把链表升级为红黑树(升级为红黑树是为了提高查找效率)
          	特殊情况 : 当底层数组的总元素和 <= 64 的时候, 就算某个链表的挂载元素>=8 也不变红黑树!
LinkedHashMap<K,V>/LinkedHashSet
HashMap<K,V> 存取无序的集合
HashSet<E> 存取无序的集合

但是如果底层数据结构增加了链表后,存取无序的集合就变成存取有序的集合!
    链表中的元素Node对象 获取上一个Node对象地址和获取下一个Node对象地址
    
LinkedHashMap<K,V>/LinkedHashSet<E> 从存取无序变为存取有序的集合
	LinkedHashMap<K,V>/LinkedHashSet<E> 分别是HashMapHashSet的子类
TreeMap<K,V>
TreeMap<K,V> : 底层为红黑树结构的Map集合实现
	红黑树结构: 去重,排序(存取无序),查询效率 
	注意 : 有排序功能就需要提供排序的规则 -> 绑定比较器和独立比较器
	TreeMap集合是双列集合,如果要提供排序规则,提供键集合元素的排序规则即可 -> 夫唱妇随
	
TreeMap中带有独立比较器的构造方法:
	TreeMap(Comparator<K> comparator) 
Hashtable<K,V>
Hashtable<K,V> 最早的双列集合,1.2版本并入到集合体系被HashMap替代.
    Hashtable<K,V>他是完美的hash表实现!!
    Hashtable<K,V>是线程安全的 --> 效率低(悲观锁)
    
    在线程安全的情况下 建议使用HashMap
    在线程不安全的情况下 建议使用ConcurrentHashMap -> 悲观锁-> 同步
    
    
Hashtable<K,V> 的子类-> Properties 属性集集合 使用非常广泛!!  
泛型
泛型 : 一种说不清楚的引用类型 

泛型的格式:<字母>
	字母: 
		1. 强烈建议大写,不建议小写-> 不规范
		2. 强烈建议单个字母,不建议多个字母 -> 不规范 
		3. 一个尖括号内可以写多个泛型 中间使用 逗号 分隔 -> <K,V>
		
泛型的使用:
	在具体使用类的时候,拿具体的引用数据类型类名去替换字母即可
	
如果有泛型存在而使用时不理会泛型,泛型默认是Object类型!!	
泛型类
泛型类 : 拥有泛型类型的类叫泛型类 ->例如 public class ArrayList<E>{}

格式:
    public class 类名<字母>{

    }

作用: 如果在类上定义了泛型类型,那么就代表在此类中 多了一种泛型类型可以直接使用!
    
在何时确定这个泛型类型的具体类型呢 ? -> 当你使用这个类的时候需要给明泛型的具体类型    

在类上定义泛型,此泛型的作用域在 整个类中有效!
泛型方法
泛型方法 : 拥有泛型类型的方法叫泛型方法

格式:
    权限修饰符 状态修饰符 <字母> 返回值类型 方法名(形参列表){
		方法体;
        //return ..;
    }
当你在方法上定义泛型类型,从此在方法内就多了一个不明确引用数据类型 给你使用! 
    具体等到调用方法时明确这个泛型类型!

在方法上定义泛型,此泛型的作用域在 整个方法中有效!
    
注意方法的泛型 一般都会在形参上使用!!
    
public static <T> boolean addAll(Collection<T> c, T... elements){方法体}  
泛型接口
泛型接口 : 拥有泛型类型的接口叫泛型接口 ->例如 public interface List<E>{}

格式:
    public interface 接口名<字母>{

    }

泛型接口的使用和泛型类一致!!
    
泛型的沿用 : 当子类实现父接口/子类继承父类的时候,如果不沿用父类/父接口的泛型,那么从子类开始就没有泛型使用了    
泛型的通配符和上限下限(重点)
    泛型的通配符 : 一般用在方法的形参上
        格式 :<?>

    泛型的上限和下限
        上限 : <? extends 类型>    传入的泛型必须是后方类型 同类型 或者 子类型
        下限 : <? super 类型> 传入的泛型必须是后方类型 同类型 或者 父类型

        不管上限还是下限都包含自己这个类型!!
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值