Java集合之Map接口与实现类详解
作者:从未止步..
初识Map
Map接口没有从Collection接口继承,Map接口用于维护“键-值”对数据,这个“键-值”对就是Map中的元素,Map提供“键(Key)”到“值(value)”的映射,一个Map中键值必须是唯一的,不能有重复的键,因为Map中的“键-值”对元素是通过键来唯一标识的,Map的键是用Set集合来存储的,所以充当键元素的类必须重写hashCode()和equals()方法,通过键元素来检索对应值元素
Map中常用方法
V put(K key, V value) //向Map集合中添加键值对 V get(Object key) //返回指定键映射到的值,通过key获取value void clear() //从此映射中删除所有映射,清空Map集合 boolean containsKey(Object key) //判断Map是否包含某个key boolean containsValue(Object value) //判断Map是否包含某个value boolean isEmpty() //判断Map中元素个数是否为0 Set<K> keySet() //获取Map集合中所有的key(所有的键都是一个“Set集合”) V remove(Object key) //通过key删除键值对,如果存在,则从该映射中移除键的映射(可选操作) int size() //获取Map集合中键值对的个数
HashMap
HashMap特点
(1)HashMap实现了Map 接口
(4)HashMap以Hash表为基础构建
(2)HashMap 允许键(Key)为空和值(Value)为空
(3)HashMap不是线程安全的,不能用在多线程环境中
HashMap常用的构造方法如下
(1)HashMap():创建一个空 HashMap 对象,并为其分配默认的初始容量和加载因子
(2)HashMap(int initialCapacity):创建一个空 HashMap 对象,并为其分配指定的初始容量
(3)HashMap(int initialCapacity,float loadFactor);创建一个空 HashMap 对象,并其分配指定的初始容量和加载因子
(4)HashMap(Map m):创建一个与给定Map 对象具有相同键-值对的 HashMap 对象
HashMap方法的简单使用
import java.security.Key; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class Warehouse1 { public static void main(String[] args){ HashMap<String,Integer> hashMap=new HashMap<>(); hashMap.put("年龄",20); hashMap.put("身高",180); hashMap.put("体重",60); System.out.println("键为年龄所对应的值为:"+hashMap.get("年龄")); System.out.println("该map是否包含键为“年龄”?"+hashMap.containsKey("年龄")); System.out.println("该map是否包含键值为90?"+hashMap.containsValue(90)); System.out.println("该map是否为空?"+hashMap.isEmpty()); System.out.println("该map的长度大小为:"+hashMap.size()); System.out.println("移除键为“体重“的键值对"+hashMap.remove("体重")); System.out.println("哈希映射中的内容如下:"+hashMap); Set<String> keys=hashMap.keySet(); Iterator<String> iterator=keys.iterator(); System.out.println("hashmap中的元素如下:"); while(iterator.hasNext()){ String s= iterator.next(); Integer name= hashMap.get(s); System.out.println(s+":"+name); } } }
输出:
键为年龄所对应的值为:20
该map是否包含键为“年龄”?true
该map是否包含键值为90?false
该map是否为空?false
该map的长度大小为:3
移除键为“体重“的键值对60
哈希映射中的内容如下:{年龄=20, 身高=180}
hashmap中的元素如下:
年龄:20
身高:180
小tips:在输出map中的元素时,我们不能直接使用iterator[迭代器],对元素进行遍历输出,因为迭代只能用在Set/List这种单列存放数据的集合中,而map是双列的,并且也不能使用foreach语句对map进行输出,因为foreach语句的本质也是迭代,只能用在单列集合中。
LinkedHashMap
LinkedHashMap有如下特点
1:LinkedHashMap实现了Map接口
2:LinkedHashMap继承了HashMap,内部还有一个双向链表维护键-值对的顺序,每个键-值对即位于哈希表中,也位于双向链表中
3:LinkedHashMap保存了两种元素顺序,输入顺序和访问顺序,插入顺序是指先添加的元素在前面,后添加的元素在后面,修改对应的元素不会影响元素的顺序,访问顺序指的是get/put操作,对一个键执行put/get操作后,其对应的键-值对会移动到链表末尾,所以最末尾的元素是最近访问的,最开始的是最久没有被访问的
4:LinkedHashMap不是线程安全的,不能用在多线程环境中
LinkedHashMap的构造方法如下
1:LinkedHashMap();构造一个空的LinkedHashMap对象
2:LinkedHashMap(Map m);构造一个具有和给定Map相同键-值对的LinkedHashMap对象
3:LinkedHashMap(int capacity):构造一个给定初始容量capacity的LinkedHashMap对象
4:LinkedHashMap(int capacity,float fillRatio):构造一个给定初始容量capacity和填充比fillRatio的LinkedHashMap对象
5:LinkedHashMap(int capacity,float fillRatio,boolean accessOrder):构造一个给定初始容量capacity,填充比fillRatio以及是否被访问顺序的LinkedHashMap对象,access-sOrder为true表示按访问顺序,否则按插入顺序。
注:前四种构造方法创建的LinkedHashMap对象都是按插入顺序
注:fillRatio是装载因子,范围在0-1.0之间,默认是0.75。当实际元素个数/容量 > fillRatio, HashMap自动进行扩容,以保证检索速度
举例:
分别创建两个LinkedHashMap对象-----linkedHashMap和linkedHashMap1
linkedHashMap是以上述五种方法中的第一种构造的LinkedHashMap对象,而linkedHashMap1是以上述五种方法中的第5种构造的LinkedHashMap对象.
代码如下:
import java.security.Key; import java.util.*; public class Warehouse1 { public static void main(String[] args){ LinkedHashMap<String,Integer> linkedHashMap=new LinkedHashMap<>(); linkedHashMap.put("number1",10); linkedHashMap.put("number2",20); linkedHashMap.put("number3",30); linkedHashMap.put("number4",40); linkedHashMap.get("number1"); linkedHashMap.get("number4"); Set <Map.Entry<String,Integer>> sets=linkedHashMap.entrySet();//Map.Entry是Map的一个内部类,表达一个 key/value映射关系 System.out.println("linkedHashMap中的元素为:"); for(Map.Entry<String,Integer> entry:sets) { System.out.println("键为:" + entry.getKey() + ",值为:" + entry.getValue()); } System.out.println("---------------"); LinkedHashMap<String,Integer> linkedHashMap1=new LinkedHashMap<String,Integer>(3,0.5f,true); linkedHashMap1.put("number1",10); linkedHashMap1.put("number2",20); linkedHashMap1.put("number3",30); linkedHashMap1.put("number4",40); linkedHashMap1.get("number1"); linkedHashMap1.get("number4"); linkedHashMap1.put("number3",1000); Set<Map.Entry<String,Integer>> set=linkedHashMap1.entrySet(); System.out.println("linkedHashMap1中的元素为:"); for(Map.Entry<String ,Integer> entry1:set) { System.out.println("键为:" + entry1.getKey() + "值为:" + entry1.getValue()); } } }
输出:
linkedHashMap中的元素为:
键为:number1,值为:10
键为:number2,值为:20
键为:number3,值为:30
键为:number4,值为:40
---------------
linkedHashMap1中的元素为:
键为:number2值为:20
键为:number1值为:10
键为:number4值为:40
键为:number3值为:1000
通过输出结果,我们不难发现,linkedHashMap中的元素输出的顺序为我们插入时的顺序,而linkedHashMap1中的元素输出顺序为访问顺序,由于这种构造对象的方法,我们设置了access-sOrder为true,因此输出顺序按访问顺序,linkedHashMap1.get(“number1”),表示访问number1,访问完之后,该键值对就移动到最后,下面两行的操作产生的影响也是这样linkedHashMap1.get(“number4”);linkedHashMap1.put(“number3”,1000)。
当按照访问顺序时,put和get去操作已经存在的Entry时,都会把Entry移动到双向链表的表尾[实际是先删除再插入]
TreeMap
TreeMap有如下特点
1:TreeMap实现了SortedMap接口
2:TreeMap和实现Map的其他对象不同的是,它不具有调优选项
3:TreeMap中所有元素必须是可比较的
4:TreeMap不是线程安全的
TreeMap的构造方法如下
1:TreeMap():构造一个空的TreeMap对象
2:TreeMap(Map m):构造一个具有和给定Map相同键-值对的TreeMap对象
3:TreeMap(Comparator c):构造一个空的TreeMap对象,并且规定特定的排列方式
4:TreeMap(SortedMap a):构造一个与给定的SortedMap具有相同键-值对,相同排列规则的TreeMap对象
TreeMap方法的简单使用
import java.util.*; public class Warehouse1 { public static void main(String[] args) { TreeMap<String,String> treeMap=new TreeMap<>(); treeMap.put("水果","苹果"); treeMap.put("汽车","奔驰"); treeMap.put("城市","西安"); System.out.println("映射中的元素是:"+treeMap); Set<String> keySet=treeMap.keySet(); Iterator<String> iterator=keySet.iterator(); System.out.println("TreeMap类实现的Map映射,按键值升序排列元素如下:"); while(iterator.hasNext()){ String it=iterator.next(); String name=treeMap.get(it); System.out.println(it+":"+name); } } }
输出:
映射中的元素是:{城市=西安, 水果=苹果, 汽车=奔驰}
TreeMap类实现的Map映射,按键值升序排列元素如下:
城市:西安
水果:苹果
汽车:奔驰
注:TreeMap默认排序规则:按照key的字典顺序来排序[升序],当然也可以通过Comparator接口,去自定义排序规则。
HashMap和TreeMap的比较
HashMap和TreeMap在实际应用中要使用哪一个,还是需要根据实际情况进行分析,在Map中插入,删除和定位元素,HashMap是最好的选择,但是如果要按顺序遍历键,那么TreeMap会更好,根据集合大小,先把元素添加到HashMap,再把这种映射转换成一个用于有序键遍历的TreeMap会更快,使用HashMap要求添加的键类明确定义了hashcode()实现,有了TreeMap实现,添加到映射的元素一定是可排序的。
Hashtable
Hashtable有如下特点
1:Hashtable实现了map接口
2:Hashtable以Hash表基础构建
3:Hashtable和HashMap在执行过程中具有一定的相似性
4:Hashtable中不允许空元素,即键和值都不允许为空
5:Hashtable是线程安全的,可以在多线程环境中使用
Hashtable的四个构造方法如下
Hashtable();创建一个空Hashtable对象,并为其分配默认的初始容量和加载因子
Hashtable(int initialcapacity);创建一个空Hashtable对象,并为其分配指定的初始容量
Hashtable(int initialcapacity,float loadFactor):创建一个空Hashtable对象,并指定其初始容量和加载因子
Hashtable(Map m);创建一个与给定Map对象具有相同键-值对的Hashtable对象
Hashtable新增的常用方法
举例:
import java.util.*; public class Warehouse1 { public static void main(String[] args) { Hashtable<String,Double> hashtable=new Hashtable<>(); hashtable.put("王俊凯",new Double(350.55)); hashtable.put("王源",new Double(3250.55)); hashtable.put("易烊千玺",new Double(1350.55)); Enumeration<String> names=hashtable.keys(); while(names.hasMoreElements()){ String name=names.nextElement(); System.out.println(name+":"+hashtable.get(name)); } double new_double=hashtable.get("易烊千玺").doubleValue(); hashtable.put("易烊千玺",new Double(new_double+2000)); System.out.println("易烊千玺的新余额为:"+hashtable.get("易烊千玺")); } }
输出:
易烊千玺:1350.55
王源:3250.55
王俊凯:350.55
易烊千玺的新余额为:3350.55
集合中元素的遍历
Collection接口的iterator()方法返回一个iterator对象,iterator接口能以迭代方式逐个访问集合中各个元素,并安全地从Collection中除去适当的元素,iterator接口中定义的方法如下所示:
iterator接口中的方法
- boolean hasNext();判断游标右边是否还有元素
- Object next();返回游标右边的元素并将游标移动到该元素后
- void remove();删除游标左边的元素,通常在next()方法之后执行,只执行一次
Enumeration接口的功能与iterator接口类似,也能够对集合中的元素进行遍历,但是Enumeration接口只对Vector,Hashtable类提供遍历方法,并且不支持移除操作,实现Enumeration接口的对象,它生成一系列元素,一次生成一个,连续调用,nextElement方法将返回一系列的连续元素
Enumeration接口中的方法
boolean hasMoreELements(); 如果存在访问的更多元素,则返回true
Object nextEment(); 返回下一个元素的引用
到此这篇关于Java集合之Map接口与实现类详解的文章就介绍到这了,更多相关Java Map接口内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!