Map用于保存具有映射关系的数据(key-vlaue)。Map的key不允许重复,即同一个Map对象的任何两个key通过equals方法比较总是返回false
Map中包含了一个keySet()方法,用于返回Map所以key组成的Set集合。
Map集合与Set集合元素的存储形式很像,如Set接口下有HashSet、LinkedHashSet、SortedSet(接口)、TreeSet、EnumSet等实现类和子接口,而Map接口下则有HashMap、LinkedHashMap、SortedMap(接口)、TreeMap、EnumMap等实现类和子接口。
Map的value非常类似List:元素与元素之间可以重复,每个元素可以根据索引(key)来查找。
Map有时也称为字典,或关联数组。
Map接口中定义如下方法:
Map接口提供了大量的实现类,如HashMap和Hashtable等,以及HashMap的子类LinkedHashMap,还有SortedMap子接口及该接口的实现类TreeMap。下面将进行详细介绍。
Map中包括一个内部类:Entry。该类封装了一个key-value对,Entry包含三个方法:
可以把Map理解成一个特殊的Set,只是该Set里包含的集合元素是Entry对象,而不是普通对象。
HashMap和Hashtable都是Map接口的实现类,Hashtable是一个古老的Map实现类,它从JDK1.0起就有,它包含两个烦琐的方法:elements()(类似于Map接口定义的values()方法)和keys()(类似于Map接口定义的keySet()方法),现在很少使用这两种方法。
两点区别:
由于HashMap里的可以不能重复,所以HashMap里最多只有一对key-value值为null,但可以有无数多项key-value对的value为null。
HashMap重写了toString()方法方法总是返回如下格式的字符串:{key1 = value1,key2 = value2..}
HashMap、Hashtable判断两个key相等的标准是:两个key通过equasl方法比较返回ture,两个key的hashCode值相等。
HashMap有一个子类:LinkedHashMap,它也是双向链表来维护key-value对的次序,该链表定义了迭代顺序,该迭代顺序与key-value对的插入顺序保持一致。
LinkedHashMap可以避免对HashMap、Hashtable里的key-value对进行排序(只要插入key-value对时保持顺序即可)。同时又可避免使用TreeMap所增加的成本。
LinkedHashMap需要维护元素的插入顺序,因此性能略低于HashMap的性能,但在迭代访问Map里的全部元素时将有很好的性能,因为它以链表来维护内部顺序。
Properties类是Hashtable类的子类,用于处理属性文件(例如Windows操作平台上的ini文件)。Properties类可以把Map对象和属性文件关联起来,从而可以把Map对象中的key-value对写入属性文件,也可以把属性文件中的属性名=属性值加载到Map对象中。由于属性文件里的属性名、属性值只能是字符串类型,所以Properties里的key、value都是字符串类型,该类提供了如下三个方法来修改Properties里的key、value值。
提供两个读、写属性文件的方法:
示例程序:
public class TestProperties { public static void main(String[] args) throws Exception { Properties props = new Properties(); //向Properties中增加属性
props.setProperty("username" , "yeeku"); props.setProperty("password" , "123456"); //将Properties中的属性保存到a.ini文件中
props.store(new FileOutputStream("a.ini") , "comment line"); //新建一个Properties对象
Properties props2 = new Properties(); //向Properties中增加属性
props2.setProperty("gender" , "male"); //将a.ini文件中的属性名-属性值追加到props2中
props2.load(new FileInputStream("a.ini") ); System.out.println(props2); } }
运行结果:
{password=123456, gender=male, username=yeeku}
Map接口派生了一个SortedMap子接口,TreeMap为其实现类。类似TreeSet排序,TreeMap也是基于红黑树对TreeMap中所有key进行排序,从而保证TreeMap中所有key-value对处于有序状态。TreeMap两种排序方法:
TreeMap中判断两个key相等的标准也是两个key通过equals比较返回true,而通过compareTo方法返回0,TreeMap即认为这两个key是相等的。
如果使用自定义的类作为TreeMap的key,应重新该类的equals方法和compareTo方法时应有一致的返回结果:即两个key通过equals方法比较返回true时,它们通过compareTo方法比较应该返回0。如果equals方法与compareTo方法的返回结果不一致,要么该TreeMap与Map接口的规则有出入(当equals比较返回true,但CompareTo比较不返回0时),要么TreeMap处理起来性能有所下降(当compareTo比较返回0,当equals比较不返回true时)。
TreeMap中提供了系列根据key顺序来访问Map中key-value对方法:
程序示例:
//R类,重写了equals方法,如果count属性相等返回true //重写了compareTo(Object obj)方法,如果count属性相等返回0;
class R implements Comparable { int count; public R(int count) { this.count = count; } public String toString() { return "R(count属性:" + count + ")"; } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj != null
&& obj.getClass() == R.class) { R r = (R)obj; if (r.count == this.count) { return true; } } return false; } public int compareTo(Object obj) { R r = (R)obj; if (this.count > r.count) { return 1; } else if (this.count == r.count) { return 0; } else { return -1; } } } public class TestTreeMap { public static void main(String[] args) { TreeMap tm = new TreeMap(); tm.put(new R(3) , "轻量级J2EE企业应用实战"); tm.put(new R(-5) , "Struts2权威指南"); tm.put(new R(9) , "ROR敏捷开发最佳实践"); System.out.println(tm); //返回该TreeMap的第一个Entry对象
System.out.println(tm.firstEntry()); //返回该TreeMap的最后一个key值
System.out.println(tm.lastKey()); //返回该TreeMap的比new R(2)大的最小key值。
System.out.println(tm.higherKey(new R(2))); //返回该TreeMap的比new R(2)小的最大的key-value对。
System.out.println(tm.lowerEntry(new R(2))); //返回该TreeMap的子TreeMap
System.out.println(tm.subMap(new R(-1) , new R(4))); } }
运行结果:
{R(count属性:-5)=Struts2权威指南, R(count属性:3)=轻量级J2EE企业应用实战, R(count属性:9)=ROR敏捷开发最佳实践}
R(count属性:-5)=Struts2权威指南
R(count属性:9)
R(count属性:3)
R(count属性:-5)=Struts2权威指南
{R(count属性:3)=轻量级J2EE企业应用实战}