首页 > 编程笔记 > Java笔记 阅读:118

Java Map接口用法详解

通义灵码
Java 中的 Set,List 接口都是 Collection 的子接口,本节要介绍的 Map 接口是与 Collection 完全独立的另外一个体系。它们之间还有一个区别,就是 Set、List、Collection 只能操作单个元素,而 Map 可以操作一对元素,因为 Map 中的元素都是以 key-value 的键值映射形式存储的。

Map 接口的定义为:
public interface Map<K, V>{}
Map 接口定义时使用了泛型,并且定义了两个泛型 K 和 V,K 表示 key,规定了键元素的数据类型,V 表示 value,规定了值元素的数据类型,Map 接口中的方法如下表所示。

方 法 描 述
int size() 获取集合长度
boolean isEmpty() 判断集合是否为空
boolean containsKey(Object key) 判断集合中是否存在某个 key 值
boolean containsValue(Object value) 判断集合中是否存在某个 value 值
V get(Object key) 取出集合中 key 对应的 value 值
v put(K key, V value) 向集合中存入一组 key-value 的元素
V remove(Object key) 删除集合中 key 对应的 value 值
void putAII(Map<? extends K, ? extends V>m) 向集合中添加另外一个 Map 集合
void clear() 清除集合中的所有元素
Set<K> keySet() 取出集合中所有的 key,返回一个 Set 集合
Collection<V> values() 取出集合中所有的 value,返回一个 Collection 集合
Set<Map.Entry<K, V>> entrySet() 将 Map 对象转换为 Set 对象
int hashCode() 获取集合的散列值
boolean equals(Object o) 比较两个集合是否相等

Map接口的实现类

Map 是一个接口,在实际开发中需要使用 Map 必须通过其实现类来完成实例化操作,Map 接口常用的实现类如下所示:
HashMap 是 Map 接口的一个常用实现类,定义如下所示:
public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> Cloneable, Serializable{}
下面的程序演示了 HashMap 的用法。
  1. public class Test {
  2. public static void main(String[] args) {
  3. HashMap<String,String> hashMap = new HashMap<String,String> ();
  4. hashMap.put("h", "Hello");
  5. hashMap.put("w", "World");
  6. hashMap.put("j", "Java");
  7. hashMap.put("s", "JavaSE");
  8. hashMap.put("m", "JavaME");
  9. hashMap.put("e", "JavaEE");
  10. System.out.println(hashMap);
  11. hashMap.remove("e");
  12. System.out.println("删除之后:"+hashMap);
  13. hashMap.put("m", "Model");
  14. System.out.println("添加之后:"+hashMap);
  15. if(hashMap.containsKey("a")) {
  16. System.out.println("集合中存在值为a的key");
  17. }else {
  18. System.out.println("集合中不存在值为a的key");
  19. }
  20. if(hashMap.containsValue("Java")) {
  21. System.out.println("集合中存在值为Java的value");
  22. }else {
  23. System.out.println("集合中不存在值为Java的value");
  24. }
  25. Set keys = hashMap.keySet();
  26. Iterator keysIterator = keys.iterator();
  27. System.out.print("集合中的key:");
  28. while(keysIterator.hasNext()) {
  29. String key = (String) keysIterator.next();
  30. System.out.print(key+",");
  31. }
  32. Collection values = hashMap.values();
  33. Iterator valuesIterator = values.iterator();
  34. System.out.print("集合中的value:");
  35. while(valuesIterator.hasNext()) {
  36. String value = (String) valuesIterator.next();
  37. System.out.print(value+",");
  38. }
  39. System.out.print("key-value:");
  40. keysIterator = keys.iterator();
  41. while(keysIterator.hasNext()) {
  42. String key = (String) keysIterator.next();
  43. String value = hashMap.get(key);
  44. System.out.print(key+"-"+value+",");
  45. }
  46. }
  47. }
运行结果为:

{h=Hello, w=World, j=Java, s=JavaSE, m=JavaME, e=JavaEE}
删除之后:{h=Hello, w=World, j=Java, s=JavaSE, m=JavaME}
添加之后:{h=Hello, w=World, j=Java, s=JavaSE, m=Model}
集合中不存在值为a的key
集合中存在值为Java的value
集合中的key:h,w,j,s,m,
集合中的value:Hello,World,Java,JavaSE,Model,
key-value:h-Hello,w-World,j-Java,s-JavaSE,m-Model,

在 Map 的实现类中,用法与 HashMap 基本一样的实现类是 Hashtable。

Hashtable 是较早推出的一个实现类,与 HashMap 的区别是:Hashtable 是线程安全的,但是性能较低;HashMap 是非线程安全的,但是性能较高。

从实际开发角度来讲,HashMap 使用的频率更高,Hashtable 的定义如下:
public class Hashtab<K, V> extends Dictionary<K, V> implements Map<K, V> Cloneable, java.io.Serializable{}
下面的实例演示了 Hashtable 的用法。
  1. public class Test {
  2. public static void main(String[] args) {
  3. Hashtable<String,String> hashtable = new Hashtable<String,String> ();
  4. hashtable.put("h", "Hello");
  5. hashtable.put("w", "World");
  6. hashtable.put("j", "Java");
  7. hashtable.put("s", "JavaSE");
  8. hashtable.put("m", "JavaME");
  9. hashtable.put("e", "JavaEE");
  10. System.out.println(hashtable);
  11. hashtable.remove("e");
  12. System.out.println("删除之后:"+hashtable);
  13. hashtable.put("m", "Model");
  14. System.out.println("添加之后:"+hashtable);
  15. if(hashtable.containsKey("a")) {
  16. System.out.println("集合中存在值为a的key");
  17. }else {
  18. System.out.println("集合中不存在值为a的key");
  19. }
  20. if(hashtable.containsValue("Java")) {
  21. System.out.println("集合中存在值为Java的value");
  22. }else {
  23. System.out.println("集合中不存在值为Java的value");
  24. }
  25. Set keys = hashtable.keySet();
  26. Iterator keysIterator = keys.iterator();
  27. System.out.print("集合中的key:");
  28. while(keysIterator.hasNext()) {
  29. String key = (String) keysIterator.next();
  30. System.out.print(key+",");
  31. }
  32. Collection values = hashtable.values();
  33. Iterator valuesIterator = values.iterator();
  34. System.out.print("集合中的value:");
  35. while(valuesIterator.hasNext()) {
  36. String value = (String) valuesIterator.next();
  37. System.out.print(value+",");
  38. }
  39. System.out.print("key-value:");
  40. keysIterator = keys.iterator();
  41. while(keysIterator.hasNext()) {
  42. String key = (String) keysIterator.next();
  43. String value = hashtable.get(key);
  44. System.out.print(key+"-"+value+",");
  45. }
  46. }
  47. }
运行结果为:

{h=Hello, w=World, j=Java, s=JavaSE, m=JavaME, e=JavaEE}
删除之后:{h=Hello, w=World, j=Java, s=JavaSE, m=JavaME}
添加之后:{h=Hello, w=World, j=Java, s=JavaSE, m=Model}
集合中不存在值为a的key
集合中不存在值为Java的value
集合中的key:h,w,j,s,m,
集合中的value:Hello,World,Java,JavaSE,Model,
key-value:h-Hello,w-World,j-Java,s-JavaSE,m-Model,

无论是 HashMap 还是 Hashtable,保存的数据都是无序的,我们可以从上面两个例子的输出结果看出这一点。Map 的另外一个实现类 TreeMap 主要功能就是按照 key 对集合中的数据进行排序,TreeMap 的定义如下:
public class TreeMap<K, V> extends AbstractMap<K, V> implements NavigableMap<K, V> Cloneable, java.io.Serializable{}
下面的实例演示了 TreeMap 的用法。
  1. public class Test {
  2. public static void main(String[] args) {
  3. TreeMap<Integer,String> treeMap = new TreeMap<Integer,String>();
  4. treeMap.put(3, "Java");
  5. treeMap.put(5, "JavaME");
  6. treeMap.put(1, "Hello");
  7. treeMap.put(6, "JavaEE");
  8. treeMap.put(2, "World");
  9. treeMap.put(4, "JavaSE");
  10. Set keys = treeMap.keySet();
  11. Iterator keysIterator = keys.iterator();
  12. while(keysIterator.hasNext()) {
  13. Integer key = (Integer) keysIterator.next();
  14. String value = treeMap.get(key);
  15. System.out.print(key+"-"+value+",");
  16. }
  17. }
  18. }
运行结果为:

1-Hello,2-World,3-Java,4-JavaSE,5-JavaME,6-JavaEE,

可以看到,无论向集合中保存数据时的顺序如何,TreeMap 内部会自动按照 key 升序对数据进行排序。此时的 key 是 Integer 类型的,那如果 key 不是一个可自动排序的数据类型,如自定义的 User 类型,TreeMap 能否对其进行排序呢?

观察下面的实例程序:
  1. public class Test {
  2. public static void main(String[] args) {
  3. TreeMap<User,String> treeMap = new TreeMap<User,String>();
  4. treeMap.put(new User(3,"Java"), "Java");
  5. treeMap.put(new User(5,"JavaME"), "JavaME");
  6. treeMap.put(new User(1,"Hello"), "Hello");
  7. treeMap.put(new User(6,"JavaEE"), "JavaEE");
  8. treeMap.put(new User(2,"World"), "World");
  9. treeMap.put(new User(4,"JavaSE"), "JavaSE");
  10. Set keys = treeMap.keySet();
  11. Iterator keysIterator = keys.iterator();
  12. while(keysIterator.hasNext()) {
  13. User key = (User) keysIterator.next();
  14. String value = treeMap.get(key);
  15. System.out.println(key+"-"+value);
  16. }
  17. System.out.println("集合中第一个Entry:"+treeMap.firstEntry());
  18. System.out.println("集合中第一个key:"+treeMap.firstKey());
  19. System.out.println("集合中最后一个Entry:"+treeMap.lastEntry());
  20. System.out.println("集合中最后一个key:"+treeMap.lastKey());
  21. System.out.println("集合中比new User(3,Java)大的最小key值:"+treeMap.higherKey (new User(3,"Java")));
  22. System.out.println("集合中比new User(3,Java)小的最大key值:"+treeMap.lowerKey(new User(3,"Java")));
  23. System.out.println("集合中比new User(3,Java)大的最小的key-value对:"+treeMap. higherEntry(new User(3,"Java")));
  24. System.out.println("集合中比new User(3,Java)小的最大的key-value对:"+treeMap. lowerEntry(new User(3,"Java")));
  25. System.out.println("截取之后的集合:"+treeMap.subMap(new User(3,"Java") , new User(5,"JavaME")));
  26. }
  27. }
  28.  
  29. class User{
  30. private int id;
  31. private String name;
  32. //getter、setter、有参构造函数、重写toString
  33. }
运行结果如下图所示。


程序运行报错,错误原因是 User 的实例化对象无法进行排序,解决方法是让 User 类实现 Comparable 接口,并在 compareTo() 方法中实现对象的排序规则,代码如下:
  1. class User implements Comparable{
  2. ……
  3. @Override
  4. public int compareTo(Object o) {
  5. // TODO Auto-generated method stub
  6. /**
  7. * A.compareTo(B)
  8. * 返回值:
  9. * 1表示A大于B
  10. * 0表示A等于B
  11. * -1表示A小于B
  12. */
  13. User user = (User) o;
  14. if(this.id > user.id) {
  15. return 1;
  16. }else if(this.id == user.id) {
  17. return 0;
  18. }else {
  19. return -1;
  20. }
  21. }
  22. }
再次运行程序,结果为:

User{id=1, name='Hello'}-Hello
User{id=2, name='World'}-World
User{id=3, name='Java'}-Java
User{id=4, name='JavaSE'}-JavaSE
User{id=5, name='JavaME'}-JavaME
User{id=6, name='JavaEE'}-JavaEE
集合中第一个Entry:User{id=1, name='Hello'}-Hello
集合中第一个key:User{id=1, name='Hello'}
集合中最后一个Entry:User{id=6, name='JavaEE'}-JavaEE
集合中最后一个key:User{id=6, name='JavaEE'}
集合中比new User(3,Java)大的最小key值:User{id=4, name='JavaSE'}
集合中比new User(3,Java)小的最大key值:User{id=2, name='World'}
集合中比new User(3,Java)大的最小的key-value对:User{id=4, name='JavaSE'}-JavaSE
集合中比new User(3,Java)小的最大的key-value对:User{id=2, name='World'}-World
截取之后的集合:{User{id=3, name='Java'}=Java, User{id=4, name='JavaSE'}=JavaSE}

通过结果可以看到,此时集合以 User 对象的 id 值升序排列为规则,对集合内的元素进行了排序,准确地讲应该是对集合中的 key 值进行排序,并且 TreeMap 支持对集合数据的多种操作。

相关文章