七叶笔记 » golang编程 » java_集合体系之Map体系总结(一)

java_集合体系之Map体系总结(一)

1、Map概述

1.1 什么是Map

映射顺序定义为迭代器在映射的 collection 视图上返回其元素的顺序,即 可以映射得到键、值和键-值的Set集合 ,元素的顺序是由得到的Set集合所决定的。某些映射实现可明确保证其顺序,如 TreeMap 类;另一些映射实现则不保证顺序,如 HashMap 类 。

1.11、Map接口

Map<K,V>,一次添加一对元素(又称键值对)。K是键,V是值。而Collection一次添加一个元素。Map集合也称为双列集合,Collection集合也称为单列集合。其实Map集合中存储的就是键值对,且保证键(K)的唯一性。

Map常用的子类:

1、Hashtable:内部结构是 哈希表 ,是同步的。不支持null作为键和值。

2、HashMap:内部结构是哈希表,不是同步的,支持null作为键和值。

3、TreeMap:内部结构是二叉树,不是同步的,支持null作为键和值。

Map接口常用的方法如下:

1、添加

value put(key,value);//返回前一个与key关联的值,如果没有则返回null

2、删除

value remove(key);//根据指定的key删除这个键值对
void clear();//清除这个Map集合 

3、判断

boolean containsKey(key);
boolean containsValue(value);
boolean isEmpty();//判断是否为空 

4、获取

value get(key);//用过键来返回值,如果没值该键返回null。当然可以通过返回null来判断是否包含指定的键(K)
int size();//获取键值对的个数 

1.12、Map接口是如何实例化的,如何遍历元素的??

这里演示一个HashMap实例化的例子:

Map< Integer ,String> map=new HashMap<Integer,String>();//实例化一个HashMap对象

注意:问题:如何获取map中的所有的元素???

取出map中的元素,原理如下:通过keySet方法获取map中所有键所在的Set集合中,再通过Set的迭代器获取到每个键。然后对每个键通过map集合的get()方法获取其所对应的值。

1.2 Map与Collection的区别

  • 1.Map 存储的是键值对形式的元素,键唯一,值可以重复。

  • 2.Collection 存储的是单列元素,子接口Set元素唯一,子接口List元素可重复。

  • 3.Map集合的数据结构值针对键有效,跟值无关,Collection集合的数据结构是针对元素有效

关于Collection可以戳这里java集合框架之Collection实例解析

2、Map继承体系

下面列出了常见Map集合的继承体系与他们的特点

3、Map泛型接口

Map特点 : 由key-value键值对组成,键不可重复,值可重复

大致包含如下功能:

  • 插入(put、putAll())、删除(remove())

  • 获取(entrySet()、get()、keySet()、size()、values())

  • 判断(containsKey()、containsValue()、equals()、isEmpty())、清除(clear())

  • 替换(replace(),replace(K key, V oldValue, V newValue) jdk1.8之后,后面示例会讲到它们)

  • void clear()
     从此映射中移除所有映射关系(可选操作)。
    boolean containsKey(Object key)
     如果此映射包含指定键的映射关系,则返回 true。
    boolean containsValue(Object value)
     如果此映射将一个或多个键映射到指定值,则返回 true。
    Set<Map.Entry<K,V>> entrySet()
     返回此映射中包含的映射关系的 Set 视图。
    boolean equals(Object o)
     比较指定的对象与此映射是否相等。
    V get(Object key)
     返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
    int hashCode()
     返回此映射的哈希码值。
    boolean isEmpty()
     如果此映射未包含键-值映射关系,则返回 true。
    Set<K> keySet()
     返回此映射中包含的键的 Set 视图。
    V put(K key, V value)
     将指定的值与此映射中的指定键关联(可选操作)。
    void putAll(Map<? extends K,? extends V> m)
     从指定映射中将所有映射关系复制到此映射中(可选操作)。
    V remove(Object key)
     如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。
    int size()
     返回此映射中的键-值映射关系数。
    Collection<V> values()
     返回此映射中包含的值的 Collection 视图。 
  • 3.1、 Map集合遍历的常见方式

    方式1、根据键获取值(key -> value)

    1.获取所有键的集合
    2.遍历键的集合,获取到每一个键
    3.根据键找值 

    方式2、根据键值对对象获取键和值( entrySet -> key,value)

    1.获取所有键值对对象的集合
    2.遍历键值对对象的集合,获取到每一个键值对对象
    3.根据键值对对象找键和值 
  • 3.11 Map使用示例

    public class MapReview {
     public static void main(String[] args) {
     Map<String, String> map=new HashMap<String, String>(); map.put("000", "qqq"); map.put("003", "rrr"); map.put("001", "www"); map.put("002", "eee"); map.put("004", "sss"); // System.out.println(map); // 直接打印输出键值对
     // 遍历1 : 通过键值对对象entrySet获取键与值
     Set<Entry<String, String>> entrySet = map.entrySet(); for (Entry<String, String> entry : entrySet) {
     String key = entry.getKey();
     String value = entry.getValue();
     System.out.println("key="+key+" value="+value);
     }
     System.out.println("-------------------"); // 遍历2 : 通过键keySet获取值
     Set<String> keySet = map.keySet(); // 得到键的集合
     for (String key : keySet) {
     String value = map.get(key);
     System.out.println("key="+key+" value="+value);
     }
     System.out.println("-------------------"); // 获取Map值的集合
     Collection<String> values = map.values();
     System.out.println(values); // 判断是否存在键和值
     System.out.println("containsKey="+map.containsKey("001"));
     System.out.println("containsKey="+map.containsValue("eee")); // 向Map集合添加元素时,若键存在,则返回之前与键对应的值
     String put = map.put("000", " aaa ");
     System.out.println("put="+put); //  output : qqq
     // default V replace(K key, V value)
     // 替换功能,将旧值替换成新值,并返回旧值(若有的话)
     String replace = map.replace("003", "666");
     System.out.println("replace="+replace);
     System.out.println(map); // default boolean replace(K key, V oldValue, V newValue
     // 只有当键key存在,并且oldValue与newValue相等时,旧的值才会被替换成新的值,并且返回true
     boolean success = map.replace("004", "sss", "lll");
     System.out.println("replace2="+success); // output : true
     }
    } 
  • 3.2、 HashMap

    3.21.HashMap的特点

    ①键是哈希表结构,可以保证键的唯一性,
    ②当向已存在key的Map中添加元素时,会覆盖掉旧值,并将旧值返回。
    ③它允许使用 null 值和 null 键,但不保证映射的顺序,特别是它不保证该顺序恒久不变(即不会保证存储的顺序与输出的顺序恒久不变)。
    ④此实现不是同步的。 

    注意

    对于自定义对象,需重写其equals和 hashCode 方法才能保证其key的唯一性

    3.22.HashMap与Hashtable的异同

    除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同 

    3.23.HashMap的使用示例

    public class HashMapReview {
     public static void main(String[] args) {
     test1();
     test2();
     } /**
     * 自定义类型做key,
     * 需重写其equals和hashCode方法才能保证其key的唯一性
     */ private static void test2() {
     HashMap<Info, String> map=new HashMap<Info, String>();
     map.put(new Info(0, "aaa"),"0000");
     map.put(new Info(1, "bbb"),"1111");
     map.put(new Info(3, "ddd"),"3333");
     map.put(new Info(0, "aaa"),"4444");
     map.put(new Info(2, "ccc"),"2222");
     printMap(map); // output:// key=Info [id=3, adress=ddd] value=3333// key=Info [id=2, adress=ccc] value=2222// key=Info [id=0, adress=aaa] value=0000// key=Info [id=1, adress=bbb] value=1111// key=Info [id=0, adress=aaa] value=4444 // 当Info没有重写equals和hashCode方法时,key出现重复元素
     } /**
     * String或基本数据类型的包装类做key,他们已重写了hashCode与equals方法
     * 键唯一,重复添加会替换旧值成新值
     */ private static void test1() {
     HashMap<String, String> map=new HashMap<String, String>();
     map.put("aaa", "123");
     map.put("bbb", "789");
     map.put("aaa", "456");
     map.put("ccc", "321");
     System.out.println(map); // output:// {aaa=456, ccc=321, bbb=789}
     // 重复的键不会重新插入,只会替换旧值成新值
     } private static void printMap(Map<Info, String> map) {
     Set<Entry<Info, String>> entrySet = map.entrySet(); for (Entry<Info, String> entry : entrySet) {
     System.out.println("key="+entry.getKey()+" value="+entry.getValue());
     }
     }
    } 

3.24 一个HashMap面试题

需求如下:

已知一个HashMap<Integer,Person>集合, Person有name(String)和age(int)属性。
请写一个方法实现对HashMap的排序功能。该方法接收HashMap<Integer,Person>为形参,返回类型为HashMap<Integer,Person>,要求对HashMap中的Person的age升序进行排序。排序时key=value键值对不得拆散。 

分析:

HashMap本身是不保证元素的顺序不变的,要对其排序可使用LinkedHashMap,它是有序的并且还是HashMap的子类,我们可以使用它来完成排序的目的。最后返回它的实例即可满足要求 并且还符合多态的编程思想 

示例代码

public class SortedHashMapDemo { public static void main(String[] args) {
 HashMap<Integer, Person> map = new LinkedHashMap<Integer, Person>();
 map.put(0, new Person("小明", 20));
 map.put(1, new Person("小二", 26));
 map.put(2, new Person("小四", 19));
 map.put(3, new Person("阿七", 33));
 map.put(4, new Person("十四", 25));
 map.put(4, new Person("小花", 19));
 System.out.println(map);
 HashMap<Integer, Person> sortedHashMap = SortedHashMap(map);
 System.out.println(sortedHashMap);
 } public static HashMap<Integer, Person> SortedHashMap(
 HashMap<Integer, Person> map) { // 获得键值对Set集合
 Set<Entry<Integer, Person>> entrySet = map.entrySet(); // 将键值对Set集合转化为List以用Collections来排序
 List<Entry<Integer, Person>> list = new ArrayList<Map.Entry<Integer, Person>>(
 entrySet); // 通过Collections来排序,添加比较器,比较年龄
 Collections.sort(list, new Comparator<Entry<Integer, Person>>() {
 @Override public int compare(Entry<Integer, Person> o1, Entry<Integer, Person> o2) { int result = o2.getValue().age - o1.getValue().age;
 result = result == 0 ? o2.hashCode() - o1.hashCode() : result; return result;
 }
 }); // 创建LinkedHashMap来存储排好序的List元素
 LinkedHashMap<Integer, Person> linkedHashMap = new LinkedHashMap<Integer, Person>(); // 遍历List,将元素添加到linkedHashMap中
 for (Entry<Integer, Person> entry : list) {
 linkedHashMap.put(entry.getKey(), entry.getValue());
 } return linkedHashMap;
 }
}
class Person {
 String name; int age; public Person(String name, int age) {
 super(); this.name = name; this.age = age;
 }
 @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]";
 }
} 

相关文章