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();        返回下一个元素的引用

作者:从未止步..原文地址:https://blog.csdn.net/m0_64365419/article/details/128180927

%s 个评论

要回复文章请先登录注册