Java基础---集合框架四(Map)

时间:2023-02-26 11:03:34

2015-4-19

一、Map集合

1、Map接口概述

     将键映射到值的对象

     一个映射不能包含重复的键

     每个键最多只能映射到一个值

2、Map接口和Collection接口的不同

              Map是双列的,Collection是单列的

              Map的键唯一,Collection的子体系Set是唯一的

              Map集合的数据结构值针对键有效,跟值无关

      Collection集合的数据结构是针对元素有效

     二者的区别:

              Collection集合:

                       单个元素:单身

                       Collection中的Set集合中,元素唯一

              Map:成对元素:夫妻,通常叫做键值对

                       Map集合中的键唯一,值可以重复

3、接口成员方法

添加功能:

     V put(K key,V value) 添加键值与值

删除功能:

     V remove(Object key) 删除一个键值的内容

     void clear() 清除内容

判断功能:

     boolean containsKey(Objectkey) 是否包含此键值

     booleancontainsValue(Object value) 是否包含此值

     boolean isEmpty() 是否为空

     int size() 集合的大小

     V get(Object key) 获取键值

获取功能:

     Set<K> keySet() 获取键值key的Set集合

     Collection<V>values()

     Set<Map.Entry<K,V>>entrySet()获得一个包含多个键值对元素的Set集合

举例:map集合遍历

     遍历方式一:

                     1: 键找值  通过指定的键,获取对应的值

                         a: 获取到Map集合中所有的键的Set集合

                         b: 遍历键的集合,得到每一个键

                         c: 通过当前的键,获取对应的值 

          //创建Map集合
Map<String,String>map = new HashMap<String,String>();
//添加元素
map.put("谢霆锋", "张柏芝");
map.put("李亚鹏", "王菲");
map.put("汪峰", "章子怡");
//遍历
//a: 获取到Map集合中所有的键的Set集合
Set<String>keys = map.keySet();
//b: 遍历键的集合,得到每一个键
for (String key :keys) {
//c: 通过当前的键,获取对应的值
Stringvalue = map.get(key);
//显示
System.out.println(key +"--" + value );
}

  遍历方式二:

              通过键值对元素对象,找对应的键,找对应的值    结婚证方式

                       a:获取所有键值对元素的Set集合

                       b:遍历Set集合,得到每一个键值对元素对象

                       c:通过键值对元素对象,获取键,获取值

方法:

   Set<Map.Entry<K,V>> entrySet(): 获得一个包含多个键值对元素的Set集合

    Map.Entry<K,V>  等价    结婚证<男的,女的>

    class 结婚证<男的,女的> {

         private 男的 man;

         private 女的 woman;

         public 男的   getMan(){

                  return man;

         }

         public 女的  getWoman(){

                  return woman;

          }

    }

   Set<Map.Entry<K,V>> entrySet = map.entrySet();

    Set<   结婚证<男的,女的>> entrySet = map.entrySet();

     代码实现:

 <span style="white-space:pre"></span>//创建Map集合
Map<String,String>map = new HashMap<String,String>();
//添加元素
map.put("谢霆锋", "张柏芝");
map.put("李亚鹏", "王菲");
map.put("汪峰", "章子怡");
//遍历
//a:获取所有键值对元素的Set集合
Set<Map.Entry<String,String>>entrySet = map.entrySet();
//b:遍历Set集合,得到每一个键值对元素对象
for (Map.Entry<String,String> entry : entrySet) {
//c:通过键值对元素对象,获取键,获取值
Stringkey = entry.getKey();//获取键
Stringvalue = entry.getValue();//获取值

System.out.println(key+"--"+ value);
}

Entry接口的结构:

Map.Entry 接口

interface Map<K,V> {

     interface Entry<K,V>{

              K getKey();

              V getValue();

              V setValue();

     }

}

class HashMap implements Map{

     static classEntry<K,V> implements Map.Entry<K,V>

              K getKey(){

                       ...

              }

              V getValue(){

                       ...

              }

              V setValue(){

                       ...

              }

     }

    

}

二、HashMap集合

1、概述

  底层:哈希表结构

             存储允许使用 null 值和 null 键

             线程不同步-- 效率高-- 不安全

           Map集合中的键要求保证唯一, 那么,HashMap集合中,如何保证 键 的唯一呢?

           重写 hashCode() 与 equals()方法

     注意:这里面的唯一指的是 键唯一, 针对键有效,  与值无关

2、案例

  举例一:使用HashSet集合存储字符串,并遍历

  方式一:

//创建HashMap集合
HashMap<String,String>hm = new HashMap<String,String>();

//添加键值对元素到集合
hm.put("谢霆锋", "张柏芝");
hm.put("李亚鹏", "王菲");
hm.put("汪峰", "章子怡");

//遍历方式1 键找值
//a: 获取到Map集合中所有的键
Set<String>keys = hm.keySet();
//b: 获取到每一个键
for (String key :keys) {
//c: 通过键,找对应的值
Stringvalue = hm.get(key);
System.out.println(key+"---"+value);
}

     方式二:

         //创建HashMap集合
HashMap<String,String>hm = new HashMap<String,String>();

//添加键值对元素到集合
hm.put("谢霆锋", "张柏芝");
hm.put("李亚鹏", "王菲");
hm.put("汪峰", "章子怡");

//遍历方式2 键值对 找键 找值
//a: 获取所有的键值对元素对象
Set<Entry<String, String>> entrySet =hm.entrySet();
//b: 获取到每一个键值对元素对象
for(Entry<String, String> entry: entrySet) {
//c: 通过当前的键值对元素对象,获取键,获取值
String key =entry.getKey();// 获取键
String value =entry.getValue(); //获取值
System.out.println(key+"---"+value);
}

  举例二:键为String,值为Student         

//创建集合对象
HashMap<String,Student>map = new HashMap<String,Student>();
//添加元素
Student s1 = newStudent("周瑜", 28);
Student s2 = newStudent("小乔", 18);
Student s3 = newStudent("大乔", 19);

map.put("itcast001",s1);
map.put("itcast002",s2);
map.put("itcast003",s3);
map.put("itcast004",s1);

//遍历
//方式1 键找值
Set<String>keys = map.keySet();
//获取到每一个键
for (String key :keys) {
//通过当前的key, 获取对应的值 Student
Students = map.get(key);
System.out.println(key+"---" + s.getName() +"---"+ s.getAge());
}

  举例三:键为Person,值为String

  注意:

  如果HashMap集合中的键是自定义类对象,那么需要重写hashCode()和equals()  

//创建集合对象
HashMap<Person,String>map = new HashMap<Person,String>();
//添加元素
Person s1 = newPerson("周瑜", 28);
Person s2 = newPerson("小乔", 18);
Person s3 = newPerson("大乔", 19);

map.put(s1,"itcast001");
map.put(s2,"itcast002");
map.put(s3,"itcast003");
map.put(s3,"itcast004");// 由于s3 键已存储, 用itcast004 替换 itcast003

//遍历 键值对 找键找值
Set<Entry<Person,String>> entrySet = map.entrySet();
//获取到每一个键值对元素对象
for (Entry<Person,String> entry : entrySet) {
Personkey = entry.getKey();
Stringvalue = entry.getValue();

System.out.println(value+"---"+ key.getName() +"---"+key.getAge() );
}

三、LinkHashMap集合

1、概述

     底层:哈希表 + 链表

              有序(元素的存与取顺序一致)

              线程不同步 -- 效率高-- 不安全

              Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。

2、案例:创建LinkHashMap集合对象遍历       

   //创建集合对象
LinkedHashMap<String,String>map = new LinkedHashMap<String,String>();
//添加元素到集合
map.put("谢霆锋", "张柏芝");
map.put("李亚鹏", "王菲");
map.put("汪峰", "章子怡");

//遍历 键找值
Set<String>keys = map.keySet();
for (String key :keys) {
//键找 值
Stringvalue = map.get(key);
System.out.println(key+"---"+value);
}

四、TreeMap集合

1、概述

      键是红黑树结构,可以保证键的排序和唯一性,实现不是同步的。

   TreeMap<K,V>

              底层:红黑树 (二叉树)

              线程不同步 -- 效率高-- 不安全

              TreeMap集合中如何保证键的唯一和排序的?

                       1:对键实现 自然排序接口 Comparable , 重写 compareTo(obj1)方法

                       2:  对键 实现比较器接口 Comparator, 重写compare(obj1,obj2)方法

举例一:使用TreeMap,遍历       

  <span style="white-space:pre"></span>// 创建TreeMap集合对象
TreeMap<String,String>map = new TreeMap<String,String>();

// 添加元素到集合
map.put("x谢霆锋", "张柏芝");
map.put("l李亚鹏", "王菲");
map.put("w汪峰", "章子怡");

//遍历键值对 找键 找值方式
Set<Entry<String,String>> entrySet = map.entrySet();
//获取到每一个键值对元素对象
for(Entry<String, String> entry : entrySet) {
//获取键
Stringkey = entry.getKey();
//获取值
Stringvalue = entry.getValue();
System.out.println(key+"---"+value);
}

举例二:<Student, String>   

  //创建TreeMap集合对象,  同时实现比较器
TreeMap<Student,String>map = new TreeMap<Student,String>(new
Comparator<Student>(){
@Override
publicint compare(Student s1, Student s2) {
//名字
intnum = s1.getName().compareTo(s2.getName());
//年龄
intresult = (num==0) ? (s1.getAge() - s2.getAge()) : num ;
returnresult;
}
});

//添加元素到集合
Student s1 = newStudent("z周瑜", 28);
Student s2 = newStudent("x小乔", 18);
Student s3 = newStudent("d大乔", 19);
map.put(s1,"itcast001");
map.put(s2,"itcast002");
map.put(s3,"itcast003");
map.put(s1,"itcast110");
//遍历
Set<Student>keys = map.keySet();
//获取到每一个键
for (Student key: keys) {
//键找 值
Stringvalue = map.get(key);
System.out.println(value+"---"+key.getName()+"---"+key.getAge() );
}

五、集合的嵌套使用

     1、案例

  举例一:根据给定的字符串得出每个字母出现的次数

              格式:a(3)b(3)c(2)d(5)e(1)

        分析:

                     通过结果可以看出 字母与次数之间有对应关系,我们可以采用Map集合

                     又由于结果是一个有序的结果,我们最终决定采用 TreeMap集合

                     a(5)

                     TreeMap<Character, Integer>

                                                 a                1++ ++

                                                 b       1

 

                     1: 定义一个字符串   "aababcabcdabcde"

                     2:定义一个集合  TreeMap<Character, Integer> 用来存储字母与次数

                     3:遍历字符串,得到每一个字母

                     4:判断当前字母在集合中是否存在

                              存在:

                                       把当前字母 在集合中存储的次数获取出来,次数加1后,再存进去

                              不存在:

                                       把当前字母  与次数1 存进去       

                     5: 组装结果字符串  a(5)b(4)c(3)d(2)e(1)

                              通过遍历Map集合得到每一个键与值 ,然后拼装

  代码实现:           

//1:定义一个字符串  "aababcabcdabcde"
String str ="aababcabcdabcde";

//2:定义一个集合 TreeMap<Character,Integer> 用来存储字母与次数
TreeMap<Character,Integer> map = new TreeMap<Character, Integer>(); // 自然排序

//3:遍历字符串,得到每一个字母
for (int i =0;i< str.length(); i++) {
//得到每一个字母
char ch= str.charAt(i);
//4:判断当前字母在集合中是否存在
if(map.containsKey(ch)) {
//把当前字母在集合中存储的次数获取出来, 次数加1后,再存进去
intcount = map.get(ch);
count++;
map.put(ch,count);

} else {
//把当前字母 与次数1 存进去
map.put(ch,1);
}
}

//System.out.println(map);
//5: 组装结果字符串 a(5)b(4)c(3)d(2)e(1)
//通过遍历Map集合得到每一个键与值 ,然后拼装
StringBuilder sb= new StringBuilder();

//方式2 键值对 找键 找值
Set<Entry<Character,Integer>> entrySet = map.entrySet();
//得到每一个键值对元素
for(Entry<Character, Integer> entry : entrySet) {
//找键 --- 字母
Characterc = entry.getKey();
//找值 --- 次数
Integern = entry.getValue();
sb.append(c).append("(").append(n).append(")");//a(5)
}
//打印结果
System.out.println(sb.toString());

  案例二:HashMap嵌套HashMap

              czbk

                     (基础班)jc

                              01     张三

                              02     李四

                     (就业班)jy

                              01     王五

                              02     赵六

           分析:

           1: 创建基础班HashMap集合    HashMap<String, String>

                                                                             学号                    姓名

           2: 向基础班集合添加元素

           3: 创建就业班HashMap集合    HashMap<String,String>

                                                                             学号                    姓名

           4: 向就业班集合添加元素

           5: 创建传智播客HashMap集合        HashMap<String, HashMap<String,String> >

                                                                         基础班                     基础班HashMap集合

                                                                             就业班                       就业班HashMap集合

           6: 向传智播客HashMap 添加元素

           7: 遍历

     代码实现:         

         //1: 创建基础班HashMap集合    HashMap<String, String>
HashMap<String,String> jc = new HashMap<String, String>();
//2: 向基础班集合添加元素
jc.put("01","张三");
jc.put("02","李四");
//3: 创建就业班HashMap集合 HashMap<String, String>
HashMap<String,String> jy = new HashMap<String, String>();
//4: 向就业班集合添加元素
jy.put("01","王五");
jy.put("02","赵六");

//5:创建传智播客HashMap集合 HashMap<String,HashMap<String, String> >
HashMap<String,HashMap<String, String>> czbk = new HashMap<String,HashMap<String, String>>();
//6:向传智播客HashMap 添加元素
czbk.put("基础班", jc);
czbk.put("就业班", jy);

//7: 遍历
//System.out.println(czbk);

// 键找 值
//所有的班级名称
Set<String>classeNames = czbk.keySet();
for (StringclasseName : classeNames) {
//每一个班级名称
System.out.println(classeName);
//通过班级名称,找到对应班级的所有学生信息
HashMap<String,String> students = czbk.get(classeName);
//获得当前班级中所有学生的学号
Set<String>ids = students.keySet();
//得到每一个学生的学号
for(String id : ids) {
//通过学号获取对应姓名
Stringname = students.get(id);
System.out.println("\t"+id+ "---"+ name);
}
}

2、面试题  ★★★

(1)HashMap和Hashtable的区别?

     HashMap:

  线程不同步--- 效率高--- 不安全

  存储的元素使用null键null值

  Hashtable

  线程同步—效率低---安全

  不能够使用null键null值作为元素

  代码举例:

 HashMap<String,String>hashMap = new HashMap<String,String>();
hashMap.put(null,"王朝");
hashMap.put("itcast110",null);
hashMap.put(null,null);
System.out.println(hashMap);

Hashtable<String,String>hashtable = new Hashtable<String,String>();
//hashtable.put(null,"马汉");//NullPointerException
//hashtable.put("itcast365",null);//NullPointerException
//hashtable.put(null,null);//NullPointerException

System.out.println(hashtable);

(2)List、Set、Map等接口是否都继承子Map接口

  Collection

           |-- List

           |--Set

  Map

       |--HashMap

       |--TreeMap

(3)你常见的集合类有哪些,都有什么方法?

              Collection

                       |- List

                                 |-ArrayList

                                 |-LinkedList

                                 |-Vector

                       |- Set

                                 |-HashSet

                                 |-TreeSet

                      

              Map

                       |-HashMap

                       |-TreeMap

                       |-Hashtable

六、Collection类

 1、概述

   针对集合操作的工具类

 2、成员方法

     public static <T>void sort(List<T> list) 排序

     public static <T>int binarySearch(List<?> list,T key) 二分查找

     public static <T> Tmax(Collection<?> coll) 最大值

     public static voidreverse(List<?> list) 反转

     public static voidshuffle(List<?> list) 随机打乱

     public static <T>boolean replaceAll(List<T> list, T oldVal, T newVal) 替换

  3、集合的结构

   集合

    |-- Collection

         |-- List

         |-- Set

|-- Map 

七、案例:通讯录实现

略。。。