本次讲解最后的Map集合框架接口和泛式集合,代码速成小秘诀,看完代码自己再敲一遍,绝对学得快
目录
一、Map
1、Map应用场景
List和Set集合都可以存储一组数据元素,每个元素是一个对象,并且可以实现对这组数据元素的操作。但是有时候需要存储具有映射关系的数据元素,如字典数据,可以通过中文找到对应的英文单词,每个元素由具有一对一关系的一组中英文数据组成,也就是一组成对的键-值对象,而不是单值数据,这样通过List集合和Set集合无法实现,需要使用到Map集合。
2、Map概述
Map集合存储若干个成对的键-值对象,提供键(key)到值(value)的映射。其中key为Set集合类型,不要求有序,不允许重复;value同样不要求有序,但允许重复。因为Map接口与Collection接口不存在继承关系,所以Map集合对象不能使用Collection接口中定义的方法,而使用特有的能够操作"键-值"的方法。
3、Map常用方法
方法 | 描述 |
Object put(Object key,Object value) | 以“键-值对”的方式进行存储。 注意:键必须是唯一的,值可以重复。如果试图添加重复的键,那么最后加入的“键-值对”将替换掉原先的“键-值对” |
Object get(Object key) | 返回指定的键所对应的值;如果此Map集合中不包含指定的键,则返回null |
int size() | 返回元素个数 |
boolen remove(Object key) | 删除指定的键映射的“键-值对” |
Set keyset() | 返回键的集合 |
Collection values() | 返回值的集合 |
boolean containsKey(Object key) | 若存在指定的键映射的“键-值对”,则返回true |
Set entrySet() | 返回“键-值对”集合 |
boolean isEmpty() | 若不存在“键-值对”元素,则返回true |
void clear() | 删除该Map对象中的所有“键-值对” |
4、HashMap集合类
1、代码示例:
运行结果:
HashMap的存储方式是哈希表。哈希表位散列表,是根据关键码值直接进行访问的数据结构。也就是说,它通过把关键码映射到表中的一个位置来访问记录,以加快查找速度。存放记录的数字被称为散列表。使用这种方式存储数据的优点是查询指定元素效率高。
2、HashMap与Hashtable
在Map接口的实现类中,除HashMap类外,Hashtable对象也可以存储"键-值"对象,Hashtable类与HashMap类具有相似的特征,Hashtable类是一个古老的Map接口实现类,它在JDK1.0中出现,当时Java还未提供Map接口。Hashtable类和HashMap类之间存在着以下典型区别。
- Hashtable类是线程安全的Map实现,但HashMap类是线程不安全的,HashMap类的性能更高,但如果多个线程访问一个Map集合对象,则应该选择Hashtable。
- Hashtable类不允许使用null作为key和value,HashMap类可以使用null作为key或value。
- 因为HashMap类里的key不能重复,所以在HaspMap类里最多只有一个"键-值"元素的key为null,但可以有无数个"键-值"的元素的value为null。
4、HashMap集合的遍历
对应Map接口来说,其本身是不能直接使用迭代(如Iterator、foreach)进行输出的。由于Map中的每个位置存入的是"键-值",而Iterator迭代器每次只能找到一个值,可以先获取所有键的集合,通过遍历键的集合,找到每个键对应的值,因此如果需要使用Iterator迭代器进行输出,则必须按照以下步骤进行操作:
- 通过KeySet()方法返回键的集合为Set集合。
- 循环遍历键的集合,获取每个键对应的值。
- 使用foreach循环或者Iterator迭代器进行遍历键。
如果以上三步看不懂,可以去看上面的贯穿案例进行剖析理解。
5、接口Map.Entry
在Map中定义了一个,用来保存形如"key-value"的元素
该接口的常用方法如下:
方法 | 描述 |
Object getKey() | 取得此键-值对应的key值 |
Object getValue() | 取得此键-值相对于的value值 |
int hashCode() | 返回该键-值的哈希码值 |
Object setValue(Object value) | 用指定的值,替换该键-值的value值 |
对应Map集合来说,是将形如"键-值"的数据保存在了Map.Entry类型的对象之后,再向集合中插入一个Map.Entry的实例化对象。
在一般的Map操作中,如添加或查询数据等操作,不需要关注Map.Entry接口,但是,在遍历Map集合中的数据时,可以使用Map.Entry接口。
6、使用接口Map.Entry遍历
7、面试常考部分内容
Hashtable | HashMap |
继承自Dictionary类 | Java1.2引进的Map interface的一个实现 |
比HashMap要古老 | 是Hashtable的轻量级实现 |
线程安全 | 线程不安全 |
不允许有null的键和值 | 允许有null的键和值 |
效率稍低 | 效率稍高 |
二、泛式集合
1、泛式集合的作用
前面讲过各集合类存储的都是Object对象,这样就会造成无论每个对象真实的数据类型是什么,一旦存储在Java集合中,集合就会忘记其真实的数据类型,把所有的对象当成Object类型处理。当程序被从集合中取出后,就需要进行强制类型转换,这种强制类型转换使代码臃肿,而且,当录入对象的数据类型与希望转换的目标类型不符时,还会引发ClassCastException异常。
从JDK1.5开始引入泛型(Generic),它有效解决了这个问题。在JDK1.5中已经改写了集合框架中的所有接口和类,增加了泛型的支持。泛型可以约束录入集合的元素类型,大大提高了数据安全性,从集合中取出数据无需进行类型转换,从而让代码更加简洁,程序更加健壮。
2、应用泛型
泛型集合可以约束集合中元素的类型,它可以把类型当作参数一样传递。泛型集合的形式为为List<E>、Map<K,V>等,其中<E>,<K,V>是集合的类型形式参数,可以在创建集合时,指定这些类型参数,即元素的数据类型,添加的元素必须为指定类型对象,保证数据的安全性。
代码示例:
运行结果:
3、常用的泛型集合
以后最常用的泛型集合就是List<E>和Map<K,V>;
使用泛型转换就无需担心是否会存在错误数据的录入导致的程序隐藏,集合中的元素类型一致,读取时就无需进行类型转换,从而使代码更加健壮和简洁。在老版本中,本来后面的new对象的尖括号中也是要写泛型的,从Java7开始,运行在构造器后不带完整的泛型信息,因此就可以不在后面的尖括号中不写泛型信息了。