Java集合系列(五)

来源:互联网 发布:机器人软件编程 编辑:程序博客网 时间:2024/05/16 08:21

前言

之前所讲解的Collection,Set,List接口都属于单值的操作,即每次只能操作一个对象,而Map接口与它们不同的是,每次操作的是一对对象,即二元偶对象,Map接口中的每一个元素都使用“key->value”的形式存储在集合中。Map的定义如下:

public interface Map<K,V>

这里写图片描述

Map.Entry接口简介

Map.Entry是使用static关键字声明的内部接口,此接口可以由外部通过”外部类.内部类”的形式直接调用。在本接口中提供了如表所示的方法:
这里写图片描述

从之前的内容可以知道,在Map接口的操作中,所有的内容都是通过key-value的形式保存数据的,那么对于集合来说,实际上是将key-value的数据保存在了Map.Entry接口的实例之后,再在Map集合中插入的是一个Map.Entry的实例化对象,如图所示:
这里写图片描述

Map接口的常用子类

与之前的Collection接口类似,如果想要使用Map接口也必须依靠其子类实例化。Map接口中常用的子类介绍如下。

  • HashMap: 无序存放的,是新的操作类,key不允许重复。
  • HashTable: 无序存放的, 是旧的操作类,key不允许重复。
  • TreeMap:可以排序的Map集合,按集合中的key排序,key不允许重复。
  • WeakHashMap:弱引用的Map集合,当集合中的某些内容不再使用时清除掉无用的数据,使用gc进行回收。
  • IdentityHashMap:key可以重复的Map集合。

新的子类:HashMap

HashMap本身是Map的子类,直接使用此类为Map接口实例化即可。
HashMap类的定义如下:

public class HashMap<K,V> extends AbstractMap<K,V>implements Map<K,V>,Cloneable,Serializable

HashMap是AbstractMap类的子类,AbstractMap类的定义如下:

public abstract class AbstractMap<K,V> extends Object implements Map<K,V>

通过使用HashMap来为读者讲解Map接口放入主要操作方法。

操作一:向集合中增加和取出内容

import java.util.HashMap;import java.util.Map;public class HashMapDemo01{public static void main(String[] args){Map<String,String>map=null;map=new HashMap<String,String>();map.put("A","a");map.put("B","b");map.put("C","c");map.put("D","d");String val=map.get("A");System.out.println("取出的内容是:"+val);  }}

在程序中通过声明Map接口对象时指定好了key和value的泛型类型为String,之后通过put()方法向Map集合中增加内容,最后通过get()方法取出一个key对应的value内容。

操作二:判断指定的key或value是否存在

import java.util.Map;import java,util.HashMap;public class HashMapDemo02{public static void main(Sting[] args){Map<String,String> map=null;map=new HashMap<String,String>();map.put("A","a");map.put("B","b");map.put("C","c");map.put("D","d");if(map.containsKey("A")){System.out.println("搜素的key存在!");}else{System.out.println("搜索的key不存在!");}if(map.containValue("a")){System.out.println("搜索的value存在!");}else{System.out.println("搜索的value不存在");

实例操作三:输出全部的key

import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Set;public class HashMapDemo03{public static void main(String[] args){Map<Strring,String> map=null;map=new HashMap<String,String>();map.put("A","a");map.put("B","b");map.put("C","c");map.put("D","d");Set<String> keys=map.keySet();  //得到全部的keyIterator<String> iter=keys.iterator(); //实例化IteratorSystem.out.print("全部的key:");while(iter.hasNext()){String str=iter.next();System.out.print(str+",");     }   } }     

实例操作四:输出全部的value

import java.util.HashMap;import java.util.Collection;import java.util.Iterator;import java.util.Map;public class HashMapDemo04{public static void main(String[] args ){Map<String,Strng> map=null;map=new HashMap<String,String>();map.put("A","a");map.put("B","b");map.put("C","c");Colection<String> values=map.values();  //得到全部的valueIterator<String> iter=values.Iterator(); //实例化IteratorSystem.out.print("全部的value:");while(iter.hasNext()){String str =iter.next();System.out.print(str+",");    }  }} 

旧的子类:Hashtable操作

Hashtable也是Map接口的一个子类,与Vector类的推出时间一样,都属于旧的操作类,其使用上也和之前没有什么太大的区别

Hashtable的操作

import java.util.Collection;import java.util.Hashtable;import java.util.Iterator;import java.util.Map;import java.util.Set;public class HashtableDemo01{public static void main(String[] args){Map<String,String> map=null;map=new Hashtable<String,String>();map.put("A","a");map.put("B","b");map.put("C","c");Set<String> keys=map.keySet(); //得到全部的keyIterator<String> iter1=keys.iterator();//实例化IteratorSystem.out.print("全部的key:"); //输出信息while(iter1.hasNext()){  //迭代输出全部的keyString str=iter.next();  //取出内容 System.out.print(str+ ",");  //输出内容}Collection<String> values=map.values(); //得到全部的valueIterator<String> iter2=values.iterator();//实例化IteratorSystem.out.print("\n全部的value:");while(iter2.hasNext()){String str =iter2.next();System.out.print(str+",");    }  }}

HashMap与Hashtable的区别

  • HashMap:采用异步处理方式,性能更高,属于非线程安全的操作类,允许null键和null值。

  • Hashtable:采用同步处理方式,性能较低,属于线程安全的操作类,不允许null键,否则将出现Null pointer Exception异常。

以上对两个类进行了比较,但是从实际的开发应用来看,HashMap类使用较多。

排序的子类:TreeMap

import java .util.Iterator;import java.util.Map;import java.util.Set;import java.util.TreeMap;public class TreeMapDemo01{public static void main(String[] args){Map<String,String> map=null; map=new TreeMap<String,String>(); //实例化map对象map.put("A","a");map.put("B","b");map.put("C","c");Set<String> keys=map.keySet();  //得到全部的keyIterator<String> iter=keys.iterator();while(iter.hasNext()){  //迭代输出String str=iter.next();  //取出keySystem.out.println(str+"__>"+map.get(str)); //取出key对应的内容     }   } }    

注意

使用自定义类做为key时必须实现Comparable接口

弱引用类:WeakHashMap

之前所讲解的Map接口的子类中的数据都是使用强引用保存的,即里面的内容不管是否使用都始终在集合中保留,如果希望集合自动清理暂时不用的数据就使用WeakHashMap类。这样,当进行垃圾收集时会释放掉集合中的垃圾信息,WeakHashMap的定义如下:

public class WeakHashMap<K,V> extends AbstractMap<K,V>implements Map<K,V>

对象的引用强度说明

Java把对象的引用分为4种级别,从而使程序更加灵活地控制对象的生命周期。这4种级别由高到低依次为:强引用,软引用,弱引用和虚引用。下面介绍这4种引用的区别。

  • 强引用:当内存不足时,JVM宁可出现OOM Error错误而使程序停止,也不会回收此对象来释放空间。

  • 软引用: 当内存不足时,会回收这些对象的内存,用来实现内存敏感的高速缓存。

  • 弱引用:无论内存是否紧张,被垃圾回收器发现立即回收。

  • 虚引用:和没有任何引用一样

Map接口的使用注意事项

1.注意事项一:不能直接使用迭代输出Map中的全部内容

对于Map接口来说,其本身是不能直接使用迭代(如Iterator,foreach)进行输出的,因为Map接口中的每一个位置存放的是一对值(key->value),而Iterator中每次只能找到一个值。所以,如果非要使用迭代输出,则必须按照以下步骤完成(以Iterator输出方法为例)。
(1) 将Map接口的实例通过entrySet()方法变为Set接口对象。
(2) 通过Set接口实例为Iterator实例化
(3)通过Iterator迭代输出,每个内容都是Map.Entry的对象。
(4)通过Map.Entry进行key-value的分离

在前面提到过,Map中的每对数据都是通过Map.Entry保存的,所以如果最终要进行输出应该使用Map.Entry接口完成。下面通过Iterator和foreach来为读者演示Map的输出。

提示

Map一般很少直接输出,只是作为查询使用

Map输出方式一:Iterator输出Map

import java.util.HashMap;import java,util.Iterator;import java.util.Map;import java.util.Set;public class IteratorDemo04{public static void main(String[] args){map<String,String> map=null;map=new HashMap<String,String>();map.put("A","a");map.put("B","b");map.put("C","c");Set<Map.Entry<String,String>> allSet=null; //声明一个Set集合,指定泛型allSet=map.entrySet(); //将Map接口实例变为Set接口实例Iterator<Map.Entry<String,String>> iter=null;iter=allSet.iterator();while(iter.hasNext()){   Map.Entry<String,String> me=iter.next(); //找到Map.Entry实例System.out.println(me.getKey()+"-->" +me.getValue)//输出key和value      }    } }     

以上操作是Map输出最标准的操作流程,读者一定要牢牢掌握,这一点在以后的开发中非常重要。

Map输出方式二:foreach输出Map

既然可以使用Iterator接口进行输出,那么也就是说使用foreach进行输出,输出时还是要将Map集合变为Set集合,Set集合中的每一个元素都是Map.Entry对象。

import java.util.Iterator;import java.util.Map;public class ForeachDemo02{public static void main(String[] args){Map<String,String> map=null; //声明map对象,指定泛型map=new HashMap<Sring,String>();  //实例化map对象map.put("A","a");map.put("B""b");map.put("C","c");for(Map.Entry<String,String> me:map.entrySet()){System.out.println(me.getKey()+"-->" +me.getValue());      }   }}      

覆写equals()和hashCode()方法

import java.util.HashMap;import java.util.Map;class Person{private Sring name;ptivate int age;public Person(String name,int age){this.name=name;this.age=age;}public boolean equals(Object obj){if(this==obj){return true;}if(!(obj instanceof Person)){return false;}Person p=(Person)obj;  //进行向下转型if(this.name.equals(p.name)&&this.age==p.age){return true;}else{return false;}}public int hashCode(){return this.name.hashCode()*this.age;}public String toString(){return "姓名:"+this.name+":年龄:"+this.age;}}public class HashMapDemo{public static void main(String[] args){Map<Person,Srting>map=null;map=new HashMap<Person,String>();Person per=new Person("张三", 30);map.put(per,"zhangsan");System.out.println(map.get(per));  }}  

程序运行结果:

zhangsan

从程序的运行结果中可以发现,如果要使用一个自定义的对象表示Map中的key,则对象所在类中一定要覆写equals()和hashCode方法;否则无法通过匿名对象找到相应的value。

总结

  • 集合的目的是用来创建动态的对象数组操作。

  • Collection接口是集合中的最大单值操作的付接口,但是一般开发中不会直接使用此接口,而常使用List或Set接口。

  • List接口扩展了Coleection接口,里面的内容是允许重复的。

  • List接口的常用子类是ArrayList和Vector,在开发中ArrayList性能较高,属于异步处理,而Vector性能较低,属于同步处理。

  • Set接口与Collection接口的定义一致,里面的内容不允许重复的,依靠Object类中的equals()和hashCode()方法来区分是否是同一个对象

  • Set接口的常用子类是HashSet和TreeSet,前者是散列存放,没有顺序;后者是顺序存放,使用Comparable进行排序操作。

  • 集合的输出要使用Iterator接口完成,Iterator属于迭代输出接口。

  • 在JDK 1.5之后集合也可以使用foreach的方式输出。

  • Enumeration属于最早的迭代输出接口,现在基本很少使用,在集合中Vector类可以使用Enumeration接口进行内容的输出

  • List集合的操作可以使用ListIterator接口进行双向的输出操作。

  • Map中的常用子类是HashMap,TreeMap,HashTable。HashMap属于异步处理,性能较高;TreeMap属于排序类,按照Comparable指定的顺序进行key的排序;Hashtable属于同步处理,性能较低。

  • 类集中提供了Collection工具类完成类集的相关操作。

  • Stack类可以完成先进后出的操作。

  • Propertics类属于属性操作类,使用属性操作类可以直接操作属性文件,属性文件可以按普通文件或者XML的文件格式进行保存。

  • 使用集合可以方便的拜师一对多及多对多的关系

原创粉丝点击