Map:键必须是唯一
同步方法:Map m = Collections.synchronizedMap(new TreeMap(...));
Hashtable:基于散列表的实现 允许空键空值 线程安全
HashMap:基于散列表的实现 允许空键空值 线程不安全 (与Hashtable基本一致)
TreeMap: 基于红黑树数据结构的实现 不允许空键空值 线程不安全
WeakHashMap:改进的HashMap,它对key实行“弱引用”,如果一个key不再被外部所引用,那么该key可以被GC回收。
在除需要排序时使用TreeSet,TreeMap外,都应使用HashSet,HashMap,因为他们的效率更高。
HashTable:
importjava.util.Hashtable;public classMain {public static voidmain(String[] args) {
Hashtable ht= newHashtable();
ht.put(new A(60000) , "11");
ht.put(new A(87563) , "22");
ht.put(new A(1232) , newB());
System.out.println(ht);//只要两个对象通过equals比较返回true,//Hashtable就认为它们是相等的value。//由于Hashtable中有一个B对象,//它与任何对象通过equals比较都相等,所以下面输出true。
System.out.println(ht.containsValue("测试字符串")); //①//只要两个A对象的count相等,它们通过equals比较返回true,且hashCode相等//Hashtable即认为它们是相同的key,所以下面输出true。
System.out.println(ht.containsKey(new A(87563))); //②//下面语句可以删除最后一个key-value对
ht.remove(new A(1232)); //③//通过返回Hashtable的所有key组成的Set集合,//从而遍历Hashtable每个key-value对
for(Object key : ht.keySet())
{
System.out.print(key+ "---->");
System.out.print(ht.get(key)+ "\n");
}
}
}classA
{intcount;public A(intcount)
{this.count =count;
}//根据count的值来判断两个对象是否相等。
public booleanequals(Object obj)
{if (obj == this)return true;if (obj!=null &&obj.getClass()==A.class)
{
A a=(A)obj;return this.count ==a.count;
}return false;
}//根据count来计算hashCode值。
public inthashCode()
{return this.count;
}
}classB
{//重写equals()方法,B对象与任何对象通过equals()方法比较都相等
public booleanequals(Object obj)
{return true;
}
}
{com.company.A@ea60=11, com.company.A@1560b=22, com.company.A@4d0=com.company.B@5451c3a8}true
truecom.company.A@ea60---->11com.company.A@1560b---->22
View Code
LinkedHashMap:
importjava.util.LinkedHashMap;public classMain {public static voidmain(String[] args) {
LinkedHashMap scores= newLinkedHashMap();
scores.put("语文" , 80);
scores.put("英文" , 82);
scores.put("数学" , 76);//遍历scores里的所有的key-value对
for(Object key : scores.keySet())
{
System.out.println(key+ "------>" +scores.get(key));
}
}
}
语文------>80英文------>82数学------>76
View Code
Properties:
importjava.io.FileInputStream;importjava.io.FileOutputStream;importjava.util.Properties;public classMain {public static voidmain(String[] args) {try{
Properties props= newProperties();//向Properties中增加属性
props.setProperty("username", "yeeku");
props.setProperty("password", "123456");//将Properties中的key-value对保存到a.ini文件中
props.store(new FileOutputStream("a.ini"), "comment line"); //①//新建一个Properties对象
Properties props2 = newProperties();//向Properties中增加属性
props2.setProperty("gender", "male");//将a.ini文件中的key-value对追加到props2中
props2.load(new FileInputStream("a.ini")); //②
}catch(Exception e){
e.printStackTrace();
}
}
}
#comment line
#Thu Nov10 13:45:53 CST 2016password=123456username=yeeku
View Code
会在项目根目录生成一个a.ini文件
importjava.io.File;importjava.io.IOException;importjava.io.PrintStream;importjava.util.Properties;public classMain {public static voidmain(String[] args) {
Properties p= newProperties();
p.setProperty("id","dean");
p.setProperty("password","123456");
System.out.println(p);try{
PrintStream fW= new PrintStream(new File("d:\\test1.properties"));
p.list(fW );
}catch(IOException e)
{
e.printStackTrace();
}
}
}
View Code
importjava.io.FileInputStream;importjava.io.FileOutputStream;importjava.util.Properties;public classMain {public static voidmain(String[] args) {try{
Properties prop= new Properties();//属性集合对象
FileInputStream fis = new FileInputStream("prop.properties");//属性文件输入流
prop.load(fis);//将属性文件流装载到Properties对象中
fis.close();//关闭流//获取属性值,sitename已在文件中定义
System.out.println("获取属性值:sitename=" + prop.getProperty("sitename"));//获取属性值,country未在文件中定义,将在此程序中返回一个默认值,但并不修改属性文件
System.out.println("获取属性值:country=" + prop.getProperty("country", "中国"));//修改sitename的属性值
prop.setProperty("sitename", "Boxcode");//添加一个新的属性studio
prop.setProperty("studio", "Boxcode Studio");//文件输出流
FileOutputStream fos = new FileOutputStream("prop.properties");//将Properties集合保存到流中
prop.store(fos, "Copyright (c) Boxcode Studio");
fos.close();//关闭流
}catch(Exception e){
e.printStackTrace();
}
}
}
TreeMap:
importjava.util.TreeMap;public classMain {public static voidmain(String[] args) {
TreeMap tm= newTreeMap();
tm.put(new R(3) , "11");
tm.put(new R(-5) , "22");
tm.put(new R(9) , "33");
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)));
}
}class R implementsComparable
{intcount;public R(intcount)
{this.count =count;
}publicString toString()
{return "R[count:" + count + "]";
}//根据count来判断两个对象是否相等。
public booleanequals(Object obj)
{if (this ==obj)return true;if (obj!=null && obj.getClass()==R.class)
{
R r=(R)obj;return r.count == this.count;
}return false;
}//根据count属性值来判断两个对象的大小。
public intcompareTo(Object obj)
{
R r=(R)obj;return count > r.count ? 1 : count < r.count ? -1 : 0;
}
}
{R[count:-5]=22, R[count:3]=11, R[count:9]=33}
R[count:-5]=22R[count:9]
R[count:3]
R[count:-5]=22{R[count:3]=11}
View Code
Set和Map的关系十分密切,java源码就是先实现了HashMap、TreeMap等集合,然后通过包装一个所有的value都为null的Map集合实现了Set集合类WeakHashMap:
importjava.util.WeakHashMap;public classMain {public static voidmain(String[] args) {
WeakHashMap whm= newWeakHashMap();//将WeakHashMap中添加三个key-value对,//三个key都是匿名字符串对象(没有其他引用)
whm.put(new String("语文") , new String("良好"));
whm.put(new String("数学") , new String("及格"));
whm.put(new String("英文") , new String("中等"));//将WeakHashMap中添加一个key-value对,//该key是一个系统缓存的字符串对象。"java"是一个常量字符串强引用
whm.put("java" , new String("中等"));//输出whm对象,将看到4个key-value对。
System.out.println(whm);//通知系统立即进行垃圾回收
System.gc();
System.runFinalization();//通常情况下,将只看到一个key-value对。
System.out.println(whm);
}
}
{英文=中等, java=中等, 数学=及格, 语文=良好}
{java=中等}
View Code
如果需要使用WeakHashMap的key来保留对象的弱引用,则不要让key所引用的对象具有任何强引用,否则将失去使用WeakHashMap的意义
IdentityHashMap:
importjava.util.IdentityHashMap;public classMain {public static voidmain(String[] args) {
IdentityHashMap ihm= newIdentityHashMap();//下面两行代码将会向IdentityHashMap对象中添加两个key-value对
ihm.put(new String("语文") , 89);
ihm.put(new String("语文") , 78);
System.out.println(ihm);//下面两行代码只会向IdentityHashMap对象中添加一个key-value对
ihm.put("java" , 93);
ihm.put("java" , 98);
System.out.println(ihm);
}
}
{语文=89, 语文=78}
{语文=89, java=98, 语文=78}
View Code
EnumMap:
importjava.util.EnumMap;public classMain {public static voidmain(String[] args) {//创建一个EnumMap对象,该EnumMap的所有key//必须是Season枚举类的枚举值
EnumMap enumMap = new EnumMap(Season.class);
enumMap.put(Season.SUMMER ,"夏日炎炎");
enumMap.put(Season.SPRING ,"春暖花开");
System.out.println(enumMap);
}
}enumSeason
{
SPRING,SUMMER,FALL,WINTER
}
{SPRING=春暖花开, SUMMER=夏日炎炎}
View Code
与创建普通Map有所区别的是,创建EnumMap是必须指定一个枚举类,从而将该EnumMap和指定枚举类关联起来
Map集合类的编程应用场景:
1) HashMap和Hashtable的效率大致相同,因为它们的实现机制几乎完全一样。但HashMap通常比Hashtable要快一点,因为Hashtable需要额外的线程同步控制2) TreeMap通常比HashMap、Hashtable要慢(尤其是在插入、删除key-value对时更慢),因为TreeMap底层采用红黑树来管理key-value对3) 使用TreeMap的一个好处就是: TreeMap中的key-value对总是处于有序状态,无须专门进行排序操作