Map 基础知识整理

怼烎@ 2022-06-02 01:49 475阅读 0赞

Map(接口):
与 Collection 并列存在。用于保存具有映射关系的数据:Key-Value。

  1. Key Value 可以是任何引用类型的数据。
  2. 其中 K 不允许重复。
  3. Map 对象所对应的类,须重写 hashCode() equals() 方法。
  4. key value 之间总存在单向一对一关系,即通过指定的 key 总能找到唯一的,确定的值。
  5. 因为 K 是唯一的,所以 keySet() 返回的是一个 Set.
  6. values() 返回的是一个 Collection
  7. 一个 K-V 对,是一个 Entry 所有的 Entry 是用 Set 存放的,也是不可重复的。

Map接口继承树:

184819_BSpv_3387637.png

184609_DOVH_3387637.png

如果右侧 Value 全为 null,看起来不就是一个 HashSet。

下为 HashSet 构造方法

private transient HashMap map;

public HashSet() {
map = new HashMap();
}

说明 HashMap 与 HshSet 底层是有关系的。

Map常用方法

190130_d4x0_3387637.png

1、map.put( null,null );//可以传一个 null 键和多个 null 值。

2、HashMap 重写了 equals 方法,所以

  1. map.put( new Person("SS"), 83);
  2. 会被 map.put( new Person("SS"), 87); 覆盖。

实例练习:

1、@Test
public void map1(){
Random rand = new Random(47);
Map m = new HashMap();
for(int i=0;i<10000; i++){
int key = rand.nextInt(20);//生成一个[0,20)之间的随机数
Integer freq = m.get(key);
m.put(key, freq==null ? 1 : freq+1);//If the map 以前包含一个该键的映射关系, 则用指定值替换旧值;
//由此得出 每个 key 生成了多少次
}
System.out.println(m);
}

2、public class MapOfList{

  1. public static Map<Person, List<? extends Pet>> petPeople
  2. = new HashMap<Person, List<? extends Pet>();
  3. static \{
  4. petPeople.put(new Person("Dawn"), Arrays.asList(new Cymric("Molly"), new Mutt("Spot")));
  5. petPeople.put(new Person("Dawn"), Arrays.asList(new Cymric("K"), new Mutt("S")));
  6. \}
  7. public static void main(String\[\] args)\{
  8. //第一种:获取 K-V 的方法(先竖着获取所有 K,再通过 K 单向映射到 V)
  9. for(Person person :petPeople.keySet() )\{
  10. System.out.printIn(person);
  11. for(Pet pet: petPeople.get(person))\{
  12. System.out.printIn(pet);
  13. \}
  14. //第二种:获取 K-V 的方法(先横着获取 K-V 对,再遍历每个 K-V 对的 K , V)
  15. for(Map.Entry<Person, List<? extends Pet>> m: petPeople.entrySet())\{
  16. String key=m.getKey();
  17. Object value=m.getValue();
  18. \}
  19. \}
  20. \}

Map 中的内部 接口

interface Entry{
K getKey();
V getValue();
V setValue(V value);
boolean equals(Object o);
int hashCode();
}

被 HashMap 中的内部类继承

static class Entry implements Map.Entry {
final K key;
V value;
Entry next;
int hash;

  1. Entry(int h, K k, V v, Entry<K,V> n) \{
  2. value = v;
  3. next = n;
  4. key = k;
  5. hash = h;
  6. \}
  7. public final K getKey() \{
  8. return key;
  9. \}
  10. public final V getValue() \{
  11. return value;
  12. \}
  13. public final V setValue(V newValue) \{
  14. V oldValue = value;
  15. value = newValue;
  16. return oldValue;
  17. \}
  18. public final boolean equals(Object o) \{
  19. if (!(o instanceof Map.Entry))
  20. return false;
  21. Map.Entry e = (Map.Entry)o;
  22. Object k1 = getKey();
  23. Object k2 = e.getKey();
  24. if (k1 == k2 || (k1 != null && k1.equals(k2))) \{
  25. Object v1 = getValue();
  26. Object v2 = e.getValue();
  27. if (v1 == v2 || (v1 != null && v1.equals(v2)))
  28. return true;
  29. \}
  30. return false;
  31. \}
  32. public final int hashCode() \{
  33. return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue());
  34. \}
  35. public final String toString() \{
  36. return getKey() + "=" + getValue();
  37. \}
  38. void recordAccess(HashMap<K,V> m) \{
  39. \}
  40. void recordRemoval(HashMap<K,V> m) \{
  41. \}
  42. \}

结论:可以看出其中的 hashCode() , equals(Object o), toString() 都被重写。

LinkedHashMap:

  1. 类比:LinkedHashSet
  2. 使用链表维护添加进 Map 中的顺序。故遍历 Map 时按添加的顺序遍历。

TreeMap:

类比: TreeSet

按照添加进 Map 中的元素的 key 的指定属性进行排序。Key 必须是同一个类对象。

TreeMap 中的 V 全部为 null 时,相当于一个 TreeSet.

自然排序 和 定制排序。

自然排序,要求: Person implements Comparable

@Override
public int compareTo(Object o){
if(o instanceof Person){
Person p =(Person)o;
int i = this.age.compareTo(p.age);
if(i == 0){
return this.name.compare(p.name);
}else{
return 1;
}
}
return 0;
}

定制排序:
public void test1(){
//实现匿名内部类
Comparator com = new Comparator(){
public int compareTo(Object o1, Object o2){
if(o1 instanceof Customer && o2 instanceof Customer){
Customer c1 = (Customer) o1;
Customer c2 = (Customer) o2;
int i = c1.getId().compareTo(c2.getId());
if(i == 0){
return c1.getName().compareTo(c2.getName());
}
return i;
}
return 0;
}
};

  1. TreeMap map = new TreeMap(com);
  2. map.put(new Customer("AA", 1001),87);
  3. map.put(new Customer("CC", 1001),87);
  4. map.put(new Customer("AA", 1002),87);
  5. map.put(new Customer("BB", 1001),87);

}

小结:

–自然排序:TreeMap 的所有的 Key 必须实现 Comparable 接口,而且所有的 Key 应该是同一个类的对象,否则将会抛出 ClasssCastException

–定制排序:创建 TreeMap 时,传入一个 Comparator 对象,该对象负责对 TreeMap 中的所有 key 进行排序。此时不需要 Map 的 Key 实现 Comparable 接口

HashMap & Hashtable

•HashMap 和 Hashtable 是 Map 接口的两个典型实现类

•区别:

–Hashtable 是一个古老的 Map 实现类,不建议使用

–Hashtable 是一个线程安全的 Map 实现,但 HashMap 是线程不安全的。

–Hashtable 不允许使用 null 作为 key 和 value,而 HashMap 可以

•与 HashSet 集合不能保证元素的顺序的顺序一样,Hashtable 、HashMap 也不能保证其中 key-value 对的顺序

•Hashtable 、HashMap 判断两个 Key 相等的标准是:两个 Key 通过 equals 方法返回 true,hashCode 值也相等。

•Hashtable 、HashMap 判断两个 Value相等的标准是:两个 Value 通过 equals 方法返回 true。

Prpperties:

Hashtable 的子类。

常用来处理属性文件,键值都为 String 类型的。

发表评论

表情:
评论列表 (有 0 条评论,475人围观)

还没有评论,来说两句吧...

相关阅读

    相关 java基础知识 整理

    1、面向对象的特征有哪些方面? 答:面向对象的特征主要有以下几个方面: \- 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只

    相关 Fragment基础知识整理

     今天主要为大家讲解一下Fragment,因为每一个项目中都会用到Fragment,还记得自己在几年前用过TabActivity来实现导航切换,那阵根本就不知道Fragmen

    相关 Map 基础知识整理

    Map(接口):     与 Collection 并列存在。用于保存具有映射关系的数据:Key-Value。     Key 于 Value 可以是任何引用类型的数据。

    相关 关于Map知识整理

    俗话说所有的上层建筑都是建立在基础之上的,所以今天给大家分享一下。 Map家族 Java为数据结构中的映射定义了一个接口java.util.Map;它有四个实现类,分别