Map
1. Map结构理解
- Map中的key:无序的、不可重复的,使用Set存储所有的key ---> key所在的类要重写equals()和hashCode()
- Map中的value:无序的、可重复的,使用Collection存储所有的value --->value所在的类要重写equals()
- 一个键值对:key-value构成了一个Entry对象,无序的、不可重复的,使用Set存储所有的entry
2. HashMap底层实现:
- 以jdk7为例:
- 实例化以后,底层创建了长度是16的一维数组Entry[] table
- map.put(key1,value1),开始检查key1是否存在,实现同上述set步骤
- 当超出临界值(且要存放的位置非空)时,扩容。默认的扩容方式:扩容为原来容量的2倍,并将原有的数据复制过来
- 以jdk8为例:
- 实例化时,底层没有创建一个长度为16的数组,首次调用put()方法时,底层创建长度为16的数组
- jdk7底层结构只有:数组+链表。jdk8中底层结构:数组+链表+红黑树。
- jdk 8底层的数组是:Node[],而非Entry[],检查key值是否存在逻辑同set
- 当数组的某一个索引位置上的元素以链表形式存在的数据个数 > 8 且当前数组的长度 > 64时,此时此索引位置上的所数据改为使用红黑树存储。
- 如果当映射关系被移除后,下次resize方法时判断树的结点个数低于6个,也会把树再转为链表。
3. 负载因子的大小对hashMap有什么影响?
- 负载因子的大小决定了HashMap的数据密度。
- 负载因子越大密度越大,发生碰撞的几率越高,数组中的链表越容易长,造成查询或插入时的比较次数增多,性能会下降。
- 负载因子越小,就越容易触发扩容,数据密度也越小,意味着发生碰撞的几率越小,数组中的链表也就越短,查询和插入时比较的次数也越小,性能会更高。但是会浪费一定的内容空间。而且经常扩容也会影响性能,建议初始化预设大一点的空间。
- 按照其他语言的参考及研究经验,会考虑将负载因子设置为0.7~0.75,此时平均检索长度接近于常数。
4. TreeMap
- 保证按照添加的键值对进行排序,实现排序遍历,
- 塞入的对象key需要考虑进行自然排序或者初始化时塞入定制排序对象。
- 底层采用红黑树的存储结构
5. Hashtable
- 线程安全,效率低
- 不能存储null的键值对
泛型
1. 泛型概念
- 把元素的类型设计成一个参数,这个参数叫做泛型。
- 就是在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。
- 这个类型参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量、创建对象时)确定(即传入实际的类型参数,也称为类型实参)
- 例如List<String>,限定list塞值时只能是String类型数据
2. 泛型的使用
- 泛型的类型只能类,不能是基本数据类型
- 定义了泛型类时,如果实例化没有指明泛型类型,则默认是object类型
- 静态方法不能使用类的泛型,因为在类加载入jvm时即产生静态方法,早于对象的创建,无法确定类的泛型参数的具体类型
- 自定义异常类不能是泛型类
3. 泛型方法
- 与方法中是否出现泛型的结构,泛型参数和类的泛型参数都没有关系
- 泛型方法定义时,在方法返回类型前 加上<E>
- 泛型方法可以声明为静态的;原因是泛型参数是在方法调用时确定的,并非在实例化时确定
4. 自定义泛型结构
- 在类/接口上声明的泛型,在本类或本接口中即代表某种类型,可以作为非静态属性的类型、非静态方法的参数类型、非静态方法的返回值类型
- 不能使用newE。但是可以:EIelements=(EJ)new Object[capacity];参考:ArrayList源码中声明:Objectll elementData,而非泛型参数类型数组。
- 父、子类泛型继承
class Father<T1,T2>{
}
//子类不保留父类的泛型
//没有类型擦除
class Sonl extends Father{//等价于class Son extends Father<Object,Object>{
}
//具体类型
class Son2 extends Father<Integer,String>{
}
//子类保留父类的泛型
//全部保留
class Son3<T1,T2>extends Father<T1,T2>{
}
//部分保留
class Son4<T2>extends Father<Integer,T2>{
}
5. 通配符的使用
- 通配符?例如List<?>,是各种List的父类
- 使用通配符的list或map都是不能写入数据的,只能读取
- 通配符的限制
- G<? extends A>:小于等于;可以作为G(A)和G(B)的父类,其中B是A的子类
- G<? super A>:大于等于;可以作为G(A)和G(B)的父类,其中B是A的父类
- <?extends Comparable>:只允许泛型为实现Comparable接口的实现类的引用调用