博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
day16_集合框架3(HashMap,TreeMap)
阅读量:4350 次
发布时间:2019-06-07

本文共 13631 字,大约阅读时间需要 45 分钟。


 

1.Map集合概述:

/*Map
:K (key)- 此映射所维护的键的类型V (Value)- 映射值的类型Map集合:该集合存储键值对.一对一对往里存.而且要保证键的唯一性*/package map;import java.util.*;class MapDemo { public static void main(String[] args) { //测试LinkedHashMap->存入顺序和取出顺序一致 //此链接列表定义了迭代顺序,该迭代顺序通常就是将键插入到映射中的顺序(插入顺序) LinkedHashMap
lm = new LinkedHashMap
(); lm.put("1","abc"); lm.put("2","bcd"); lm.put("3","abc"); lm.put("4","abcd"); lm.put("5","abc"); System.out.println(lm); lm.put("5","defg"); System.out.println(lm); }}/* 重要的实现类: Hashtables:底层是哈希表数据结构,不可以存入null键null值.HashTable是线程同步的.效率低 JDK 1.0 为了成功地在哈希表中存储和获取对象,用作键的对象必须实现 hashCode 方法和 equals 方法。 HashMap:底层是哈希表数据结构,可以存入null键null值.HashMap是线程非同步的.效率高 JDK1.2 依然需要实现hashCode和equals TreeMap:①底层是红黑树(自平衡二叉查找树)数据结构.线程不同步. ②可以用于给map集合中的键(Key)进行排序和Set很像. 其实,set底层就是使用了Map集合 HashSet 底层用到了 HashMap 很好解释了为什么要复写hashCode和equals TreeSet 底层用到了 TreeMap 而TreeMap运用的就是红黑树*/

2.Map常用操作:

/*一些常用操作: 1.添加  V put(K key, V value)           将指定的值与此映射中的指定键关联(可选操作)。  void putAll(Map
m) 从指定映射中 将所有映射关系 复制到此映射中(可选操作)。 2.删除 void clear() V remove(Object key) 如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。 3.判断 boolean containsKey(Object key) 如果此映射包含 指定键的映射关系,则返回true. boolean containsValue(Object Value) 如果此映射将 一个或多个键映射到指定值 ,则返回true. 4.获取 V get(Object key) 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。 int size() 返回此映射中的 键-值映射 关系数。 Collection
values() 返回此映射中包含的值(Value)的 Collection 视图。 ※Set
> entrySet() 返回此映射中包含的映射关系的 Set 视图。 ※ Set
keySet() 返回此映射中包含的键的 Set 视图。 */package map;import java.util.*;class MapDemo2{ public static void print(Object obj){ System.out.println(obj); } public static void main(String[] args){ Map
map = new HashMap
(); //添加元素 print("put "+map.put("01","zhangsan"));//null 原来HashMap中没有01对应的value->返回null print("put "+map.put("01","heihei"));//zhangsan 返回旧的01对应的heihei,并且把01对应的zhangsan替换掉(保证key唯一性) /* 也就是说,在添加时,新的key=value与旧的key=value 出现key相同->新value会覆盖旧value,并且返回旧value. */ map.put("02","Lisi"); map.put("03","wangwu"); print("containsKey: "+map.containsKey("04"));//false print("remove04: "+map.remove("04"));//null print("remove02: "+map.remove("02"));//Lisi print(map);//{01=zhangsan,03=wangwu}//依然元素转换成字符串形式输出,使用的是AbstractMap中的toString(); //注意打印顺序和存入顺序可能不同->底层使用的为哈希表 //获取 print("get01: "+map.get("01"));//zhangsan print("get04: "+map.get("04"));//null map.put(null,"maliu");//虽然可以加入,但没有意义 map.put("04",null);//同上 //可以通过get方法的返回值来判断一个键是否存在,返回是否为null判断 Collection
coll = map.values(); print(coll); print(map); }}

3.entrySet()与keySet()

 

/*怎样将Map中所有value,Key取出?1.Set
keySet() 将Map中所有的Key存入到Set集合. 因为set集合具备迭代器.利用迭代器取出Key, 根据Map中的get方法, 获取每一个键对应的值. Map集合的取出原理:将map集合转成set集合,在通过迭代器取出 (画一个示意图)2.Set
> entrySet() 将map结合中的映射关系存入到了set集合中,而这个关系的数据类型就是Map.Entry (画一个示意图) Map.Entry:表示Map中的关系类型而Map.Entry
:指定关系中Key和Value的操作类型 Set
>:泛型嵌套老毕经典比喻:(霸气侧漏(*^__^*)) 假如存入的键值对为丈夫和妻子(当然了一夫一妻制:一个丈夫对应一个妻子) ①keySet:把Map中的丈夫取出来放在Set->通过丈夫找出对应的妻子 ②entrySet:把Map中的丈夫和妻子的关系取出来(假设为结婚证)->存放在Set中 ->通过结婚证,结婚证上有丈夫和妻子啊(Map.Entry) ->调用结婚证特有方法(getKey,getValue) ->获取到丈夫和妻子*/package map;import java.util.*;class MapDemo3{ public static void main(String[] args){ Map
map = new HashMap
(); map.put("02","zhang"); map.put("03","wang"); map.put("04","xu"); //获取map集合中所有key的Set集合 Set
s = map.keySet();//Set
里面指明key的泛型,因为获取的是key的集合 for(Iterator
it = s.iterator();it.hasNext();) System.out.println(map.get(it.next())); //entrySet方法,注意用的HashMap存入和取出的顺序不一定一致 Set
> s2= map.entrySet(); for(Iterator
> it2 = s2.iterator();it2.hasNext(); ){ Map.Entry
me=it2.next(); System.out.println(me.getKey()+"..."+me.getValue()); } }}/*分析Map.Entry:其实Entry也是一个接口,它是Map接口中的一个内部接口.src中: //接口经过编译后生成.class文件,可以类比下 内部类 public interface Map
{ public static interface Entry
{ K getKey(); V getValue(); V setValue(V value); } }为什要把Entry定义在Map内部? Entry表示Map中Key与Value的关系,其实Key和Value被
封装在了Entry类(HashMap中一个内部类实现了Map中的Entry接口)中.
 
static class Entry
implements Map.Entry
{ final K key; V value; Entry
next; int hash; Entry(int h, K k, V v, Entry
n) { value = v; next = n; key = k; hash = h; } public final K getKey() { return key; } public final V getValue() { return value; } public final V setValue(V newValue) { V oldValue = value; value = newValue; return oldValue; } ..... } */

 

 

keySet()方法:

entrySet()方法:

4.HashMap集合示例:

/*每一个学生都有对应的归属地学生Student,地址String.学生属性:姓名和年龄相同的视为同一个学生保证学生的唯一性*///描述学生//注意这里需要存入到HashMap中//之前HashSet之所以需要复写hashCode和equals//
因为底层用的其实是HashMap(更确切的说是哈希表) //
为了能够实现对哈希表中的元素进行存储和获取->用作Key的对象需要复写这两个方法 //
要想存入到HashMap中,更需要复写package map;import java.util.*;class Student implements Comparable
{
//如果Studet继承Person使用Person扩展性更好 private String name; private int age; Student(String name,int age){ this.name=name; this.age=age; } public int hashCode(){ return name.hashCode()+age*37; } public boolean equals(Object obj){ if(!(obj instanceof Student)) // return false; 返回false没意义,因为不同对象比较没意义 throw new ClassCastException("类型不匹配");//比较好 else return this.name==((Student)obj).name && this.age==((Student)obj).age; } //按姓名比较 public int compareTo(Student stu){ int num=this.name.compareTo(stu.name); if(num==0) return this.age-stu.age; else return num; } public String getName(){ return name; } public int getAge(){ return age; }}class MapTest{ public static void main(String[] args){ Map
map = new HashMap
(); map.put(new Student("01",12),"abc"); map.put(new Student("01",12),"bcd");//与第一个key相同,value不同 map.put(new Student("01",12),"abc");//与第一个key,value均相同 map.put(new Student("02",23),"abc");//与第一个key不同,value相同 /* 取出结果: entrySet: keySet: 01-12-abc abc 02-23-abc abc */ //keySet //Set
s = map.keySet(); for(Iterator
it = map.keySet().iterator();it.hasNext(); ){ System.out.println(map.get(it.next())); } //entrySet //Set
> s2 = map.entrySet(); for(Iterator
> it = map.entrySet().iterator();it.hasNext(); ){ Map.Entry
me=it.next(); Student stu = me.getKey(); System.out.println(stu.getName()+"..."+stu.getAge()+"..."+me.getValue()); } }}

 

5.TreeMap示例:

/* TreeMap:底层数据结构:红黑树(Red-Black tree)该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。TreeMap中不允许存入null Key,会发出NullPointerException,但可以存入null value.因为null Key与null Key比较无意义. */ import java.util.*; class TreeMapDemo{    public static void main(String[] args){        TreeMap
tm = new TreeMap
(); //tm.put(null,"123");//NullPointerException tm.put("123","12"); //tm.containsKey(null);//NullPointerException // tm.get(null);//NullPointerException } }
/*需求:对学生对象的年龄进行升序排序  因为数据是以键值对形式存在的. 所以要使用可以排序的Map集合-TreeMap */package map;import java.util.*;//自定义比较器,按年龄进行比较class MyComp implements Comparator
{ public int compare(Student stu_1,Student stu_2){ int num=stu_1.getAge()-stu_2.getAge(); if(num==0) return stu_1.getName().compareTo(stu_2.getName()); return num; }}class MapTest2{ public static void printMap(Map
map){ for(Iterator
> it = map.entrySet().iterator();it.hasNext(); ){ // map.entrySet().iterator();//首先获得一个存储关系对象的集合实体 Map.Entry
me=it.next(); //调用iterator()获取一个相应的迭代器实体 Student stu = me.getKey(); System.out.println(stu.getName()+"..."+stu.getAge()+"..."+me.getValue()); } } public static void main(String[] args){ Map
map = new TreeMap
(new MyComp()); map.put(new Student("zhang",18),"BJ"); map.put(new Student("liu",12),"SH"); map.put(new Student("wang",20),"NJ"); map.put(new Student("xu",16),"TJ"); //在构造一个新的TreeMap,使用自然顺序排序 Map
map2 = new TreeMap
(map); System.out.println(map);//输出map集合,其中按Key从小到大顺序排列 //但这样输出的Key为对象字符串形式. printMap(map); System.out.println("\n"); printMap(map2); }}

6.TreeMap练习2:

/*"sdfgzxcvasdfxcvdf"获取该字符串中的字母出现次数希望打印结果:a(1)c(2)......每一个字母都有对应的次数.说明字母和次数之间都有映射关系当发现有映射关系(一个对应一个)时,可以选择map集合什么时候使用map集合? 像上面的情况那样(数据之间存在映射关系)->首先考虑map集合思想:  ①首先把字符串转化成字符数组    ②拿着字符去map集合中遍历->遍历完未找到a(可以令其返回null)->存入a,1(表示出现一次)                           ->找到转③  ③说明a在map中存在对应的key,此时,取出a对应的value->令value自增->重新存入    ④其余字符同理*/package map;import java.util.*;class TreeMapTest{   //方法一:利用containsKey     public static String charCount(String str,Map
tm){ char[] ch = str.toCharArray();//转换成字符数组,便于操作 for(int i=0;i
转换成指定格式的字符串返回 for(Iterator
>it=tm.entrySet().iterator();it.hasNext();){ Map.Entry
me=it.next(); sb.append("("+me.getKey()+")"+me.getValue()); } return sb.toString(); } //方法二:利用get public static String charCount_2(String str,Map
tm){ char[] ch = str.toCharArray(); for(int i=0,count=0;i
'z')&&(ch[i]<'A'||ch[i]>'Z'))//非字母字符,不再计数 continue; Integer value=tm.get(ch[i]); if(value!=null) count=value;//count简化了两次调用put ++count; tm.put(ch[i],count); /* if(value==null)//Key没有对应的Value,返回null,加入集合 tm.put(ch[i],1); else tm.put(ch[i],value+1); */ } String mapStr="";//存储集合字符串形式 //利用entrySet->转换成指定格式的字符串返回 for(Iterator
>it=tm.entrySet().iterator();it.hasNext();){ Map.Entry
me=it.next(); mapStr += "("+me.getKey()+")"+me.getValue(); } return mapStr; } public static void main(String[] args){ TreeMap
tm = new TreeMap
(); String str = "abae+c"; //System.out.println(charCount(str,tm)); //如果再次使用同一个Map,第二种方法,在遍历a时,会把a对应的Value+1 System.out.println(charCount_2(str,tm)); }} /* //TreeMap/HashMap在使用迭代器方法时,使用了集合的增,删方法时,也会报并发修改异常 tm.put('b',1); while(it.hasNext()) { tm.put('a',1); System.out.println(it.next()); } */ /* 总结:该题和以前做过的一个去除集合中的重复元素 使用的同一个算法: ①新建一个集合容器 ②每次添加看看该容器是否包含添加的元素 ③有则不在添加,没有则加入. */

 

7.Map扩展(Map中嵌套Map/Set/List)

①Map集合的Value为Map

/*
<掌握这个思想>
Map扩展:(一对多映射/集合中嵌套集合/集合中存取集合对象)例如:预热班-01-zhangsan预热班-02-lisi就业班-01-maliu(示意图)*/package map;import java.util.*;class MapExtend{ //取出学生:先找学校->再找班级->最后取学生 public static void getStu(Map
>map,String classes){ //方法一:利用entrySet只取预热班学生 for(Iterator
>> it = map.entrySet().iterator();it.hasNext(); ){ Map.Entry
> mn=it.next(); if(mn.getKey()=="预热班"){ //如果把该条件去掉,取出所有班级的学生 for(Iterator
>itValue=mn.getValue().entrySet().iterator();itValue.hasNext();){ Map.Entry
me = itValue.next(); System.out.println(mn.getKey()+"..."+me.getKey()+"..."+me.getValue()); } } } } //方法二 熟练下keySet public static void getStu_2(Map
>map,String classes){ //利用entrySet只取预热班学生 for(Iterator
it = map.keySet().iterator();it.hasNext(); ){ //遍历取出班级 String bj= it.next();//存放班级 if(bj=="就业班"){ HashMap
hm;//为了存放下面取出的集合对象 for(Iterator
itValueKey = (hm=map.get(bj)).keySet().iterator();itValueKey.hasNext(); ){ String number = itValueKey.next(); System.out.println(classes+"..."+number+"..."+hm.get(number)); } } } } public static void main(String[] args){ //类比:先有学校->再有教室->最后有了学生 TreeMap
> tm = new TreeMap
>();//集合中存入集合对象 HashMap
hm_1 = new HashMap
();//第一个教室 HashMap
hm_2 = new HashMap
();//第二个教室 tm.put("预热班",hm_1);//添加班级 tm.put("就业班",hm_2); hm_1.put("01","zhangsan");//添加学生 hm_1.put("02","lisi"); hm_2.put("03","zhangsan"); hm_2.put("04","lisi"); System.out.println(tm); getStu(tm,"预热班"); System.out.println(); getStu_2(tm,"就业班"); } }

 

 

②Map中的Value为List集合

/*对于前面那个例子:预热班-01-zhangsan预热班-02-zhangsan就业班-03-wangwu就业班-04-wangwu如果把学号和姓名封装成一个学生对象.那么预热班-许多学生对象就业班-许多学生对象(示意图)*/package map;import java.util.*;class Student{ private String id; private String name; Student(String id,String name){  this.id=id;  this.name=name; } public String toString(){   return id+"..."+name;  }}class MapExtend2{    public static void getStu(HashMap
> hm){ //使用Map的keySet for(Iterator
it = hm.keySet().iterator();it.hasNext(); ){
//遍历Map集合 String bj=it.next();//取出班级 for(Iterator
itList=hm.get(bj).iterator();itList.hasNext();){
//遍历取出的List集合 Student stu=itList.next(); System.out.println(bj+"..."+stu); } } } public static void main(String[] args){ HashMap
> hm = new HashMap
>();//Value的值为List集合对象 List
list_1 = new ArrayList
();//list存放学生对象 List
list_2 = new ArrayList
(); list_1.add(new Student("01","zhangsan")); list_1.add(new Student("02","wangwu")); list_2.add(new Student("03","maliu")); list_2.add(new Student("04","zhangsan")); hm.put("预热班",list_1); hm.put("就业班",list_2); getStu(hm);
}}

转载于:https://www.cnblogs.com/yiqiu2324/archive/2013/04/17/3027383.html

你可能感兴趣的文章
[复合材料] 编织复合材料单胞周期性边界条件编程问题
查看>>
Paxos协议笔记
查看>>
php之快速入门学习-15(php函数)
查看>>
【01背包问题】
查看>>
我所知道的数据库8-DML语言
查看>>
Python学习笔记——面向对象基础
查看>>
SQL Server 2012安装时如何不安装自带的Visual Studio
查看>>
网络传输协议总结(转载)
查看>>
C#.NET 大型企业信息化系统集成快速开发平台 4.2 版本 - 角色权限的配置页面改进优化...
查看>>
如何编写Spring-Boot自动配置
查看>>
(三)Asp.net web api中的坑-【http post请求中的参数】
查看>>
洛谷跑路
查看>>
使用DbProviderFactories.GetFactory方法需要配置数据库提供者
查看>>
Ubuntu || LinuxMint 配置apache虚拟主机
查看>>
HTML—链接
查看>>
将进程设置为守护进程
查看>>
用连接池提高Servlet访问数据库的效率
查看>>
luogu P1494 [国家集训队]小Z的袜子 ( 普 通 )
查看>>
树的数据结构
查看>>
MyEclipse导入Color Theme
查看>>