Java学习笔记一Map集合

迷南。 2023-07-24 03:19 35阅读 0赞

Map的key不允许重复,即同一个Map对象的任何两个key通过equals方法比较总是返回false。key和value之间存在单向一对一关系,即通过指定的key,总能找到唯一的、确定的value。
如果把Map里的所有key放在一起来看,它们就组成了一个set集合,实际上Map确实包含了一个keySet方法,用于返回Map里所有key组成的Set集合。
虽然Map中放的元素是key-value对,Set集合中放的元素是单个对象,但如果把key-value对中的value当成key的附庸:key在哪里,value就跟在哪里。这样就可以像对待set一样对待map了。事实上,Map提供了一个Entry内部类来封装key-value对,而计算Entry存储时则只考虑Entry封装的key。从Java源码来看,Java是先实现了Map,然后通过保证一个所有value都为null的Map就实现了set集合。
Entry类包含如下三个方法:Object getKey()返回该Entry里包含的key值,Object getValue()返回该Entry里包含的value值,Object setValue(V value)设置该Entry里包含的value值,并返回新设置的value值。

Hashtable

Hashtable是一个古老的线程安全的Map实现类,从JDK 1.0起就已经出现了,当它出现时,Java还没提供Map接口,所以它包含了两个烦琐的方法,即elements(类似于Map接口定义的values方法)和keys(类似于Map接口定义的keySet方法)。Hashtable不允许使用null作为key或value,如果试图把Null值放进Hashtable中,将会引发NullPointerException异常。

Properties

Java学习笔记一Properties类

HashMap

线程不安全,HashMap可以使用null作为key或value。由于HashMap里的key不能重复,所以HashMap里最多只有一个key-value对的key为null,但可以有无数多个key-value对的value为null。

LinkedHashMap

LinkedHashMap使用双向链表来维护key-value对的次序,该链表负责维护Map的迭代顺序,迭代顺序与key-value对的插入顺序保持一致

  1. LinkedHashMap scores = new LinkedHashMap();
  2. socres.put("语文",80);
  3. socres.put("英语",82);
  4. socres.put("数学",76);
  5. scores.forEach((key,value)->System.out.println(key+"--->"+value));

为了成为地在HashMap、Hashtable中存储、获取对象,用作key的对象必须实现hashCode()方法和equals()方法。HashMap、Hashtable判断两个value相等的标准,只要两个对象通过equals方法比较返回true即可。

  1. class A
  2. {
  3. int count;
  4. public A(int count){ this.count = count; }
  5. //根据count值来判断两个对象是否相等
  6. public boolean equals(Object obj){
  7. if(obj == this) return true;
  8. if(obj != null && obj.getClass() == A.class){
  9. A a = (A)obj;
  10. return this.count == a.count;
  11. }
  12. return false;
  13. }
  14. //根据count来计算hashCode值
  15. public int hashCode(){ return this.count; }
  16. }
  17. class B
  18. {
  19. //重写equals方法,B对象与任何对象通过equals方法比较都返回true
  20. public boolean equals(Object obj){ return true; }
  21. }
  22. public class HashtableTest
  23. {
  24. public static void main(String[] args)
  25. {
  26. Hashtable ht = new Hashtable();
  27. ht.put(new A(60000), "疯狂Java讲义");
  28. ht.put(new A(87563), "疯狂JavaScript讲义");
  29. ht.put(new A(1232), new B());
  30. System.out.println(ht);
  31. // 只要两对象通过equals方法比较返回true,Hashtable就认为它们是相等的value
  32. // 由于Hashtable中有一个B对象,它与任何对象通过equals方法比较都相等,所以下面输出true
  33. System.out.println(ht.containsValue("测试字符串")); //输出true
  34. // 只要两个A对象的count相等,它们通过equals方法比较返回true,且hashCode值相等,Hashtable就认为它们是相等的key
  35. System.out.println(ht.containsKey(new A(87563))); //输出true
  36. //下面语句删除最后一个key-value
  37. ht.remove(new A(1232));
  38. }
  39. }

SortMap接口

TreeMap

TreeMap是一个红黑数结构,每个key-value对即作为红黑树的一个节点。TreeMap存储key-value对时,需要根据key对节点进行排序。TreeMap可以保证所有的key-value对处于有序状态。TreeMap有自然排序和定制排序。
自然排序:所有key必须实现Compare接口,而且所有的key应该是同一个类的对象,否则将会抛出ClassCastException异常。
定制排序:创建TreeMap时,传入一个Comparator对象,该对象负责对TreeMap中的所有key进行排序。采用定制排序时不要求Map的key实现Comparable接口。
TreeMap中判断两个key相等的标准是:两个Key通过compareTo方法返回0,TreeMap即认为这两个key是相等的。如果使用自定义类作为TreeMap的key,且想让TreeMap良好地工作,则重写该类的equals方法和compareTo方法时应保持一致的返回结果:两个key通过equals方法比较返回true时,它们通过compareTo方法比较应该返回0。如果equals方法和compareTo方法的返回结果不一致,TreeMap与Map接口的规则就会冲突。

  1. class R implements Comparable
  2. {
  3. int count;
  4. public R(int count){ this.count = count; }
  5. public String toString(){ return "R[count:"+count+"]"; }
  6. public boolean equals(Object obj)
  7. {
  8. if(this == obj) return true;
  9. if(obj!=null && obj.getClass() == R.class)
  10. {
  11. R r = (R)obj;
  12. return r.count == this.count;
  13. }
  14. return false;
  15. }
  16. public int compareTo(Object obj)
  17. {
  18. R r = (R)obj;
  19. return count > r.count ? 1:count < r.count ? -1:0;
  20. }
  21. }
  22. public class TreeMapTest
  23. {
  24. public static void main(String[] args)
  25. {
  26. TreeMap tm = new TreeMap();
  27. tm.put(new R(3), "轻量级Java EE企业应用实战");
  28. tm.put(new R(-5), "疯狂Java讲义");
  29. tm.put(new R(9), "疯狂JavaScript讲义");
  30. System.out.println(tm);
  31. //返回该TreeMap的第一个Entry对象
  32. System.out.println(tm.firstEntry());
  33. //返回该TreeMap的最后一个key值
  34. System.out.println(tm.lastkey());
  35. //返回该TreeMap的比new R(2)大的最小key值
  36. System.out.println(tm.higherKey(new R(2)));
  37. //返回该TreeMap的比new R(2)小的最大key-value对
  38. System.out.println(tm.lowerEntry(new R(2)));
  39. //返回该treeMap的子TreeMap
  40. System.out.println(tm.subMap(new R(-1), new R(4)));
  41. }
  42. }

WeakHashMap

WeakHashMap与HashMap的用法基本相似。与HashMap的区别在于,HashMap的key保留了对实际对象的强引用,这意味着只要该HashMap对象不被销毁,该HashMap的所有key所引用的对象就不会被垃圾回收,HashMap也不会自动删除这些key所对应的key-value对;但WeakHashMap的key只保留了对实际对象的弱引用,者意味着如果WeakHashMap对象的key所引用的对象没有被其他强引用变量所引用,用这些key所引用的对象可能被垃圾回收,WeakHashMap也可能自动删除这些key所对应的key-value对。WeakHashMap中的每个key对象只持有对实际对象的弱引用,因此,当垃圾回收了该key所对应的实际对象之后,WeakHashMap会自动删除该Key对应的key-value对。

IdentityHashMap

在IdentityHashMap中,当且仅当两个key严格相等(key1==key2)时,IdentityHashMap才认为两个key相等;对应普通的HashMap而言,只要key1和key2通过equals方法比较返回true,且它们的hashCode值相等即可。

EnumMap

EnumMap是一个与枚举类一起使用的Map实现,EnumMap中的所有key都必须是单个枚举类的枚举值。创建EnumMap时必须显式或隐式指定它对应的枚举类。EnumMap在内部以数组形式保存,所以这种实现形式非常紧凑高效。EnumMap根据key的自然顺序(即枚举值在枚举类中的定义顺序)来维护key-value对的顺序。当程序通过keySet、entrySet、values等方法遍历EnumMap时可以看到这种顺序。EnumMap不允许使用null作为key,但允许使用null作为value。如果试图使用null作为key时将抛出NullPointerException异常。如果只是查询是否包含值为null的key,或只是删除值为null的key,都不会抛出异常。

  1. enum Season
  2. {
  3. SPRING,SUMMER,FALL,WINTER
  4. }
  5. public class EnumMapTest
  6. {
  7. public static void main(String[] args)
  8. {
  9. //创建EnumMap对象,该EnumMap的所有key都是Season枚举类的枚举值
  10. EnumMap enumMap = new EnumMap(Season.class);
  11. enumMap.put(Season.SUMMER, "夏日炎炎");
  12. enumMap.put(Season.SPRING, "春暖花开");
  13. System.out.println(enumMap); //{SPRING=春暖花开, SUMMER=夏日炎炎}
  14. }
  15. }

发表评论

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

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

相关阅读

    相关 Java学习笔记Map集合

    Map的key不允许重复,即同一个Map对象的任何两个key通过equals方法比较总是返回false。key和value之间存在单向一对一关系,即通过指定的key,总能找到唯

    相关 学习笔记Java集合——Map

    我们常会看到这样的一种集合:身份证号与个人,学号与学生个体,系统用户名与系统用户对象等,这种一一对应的关系,就叫做映射。Java提供了专门的集合类用来存放这种对象关系的对象,即