Java中的集合Map、HashMap、Hashtable、Properties、SortedMap、TreeMap、WeakHashMap、IdentityHashMap、EnumMap(五)

  • Map

  Map用于保存具有映射关系的数据,因此Map集合里保存着两组值,一组值用于保存Map里的key,另一组值用于保存Map里的value,key和value都可以是任何引用类型的数据。Map的key不容许重复,即同一个Map对象的任何两个key通过equals方法比较总是返回false。

  key和value之间存在单向一对一关系,即通过指定的key,总能找到唯一的、确定的value。从Map中取出数据时,只要给出指定的key,就可以取出对应的value。

  如果把Map里的所有key放在一起看,它们就是一个Set集合,实际上Map确实包含一个keySet()方法,用于返回Map所有key组成的Set集合。如下:

public class Test {
    public static void main(String[] args){
        Map<String, String> mapVal = new HashMap<String, String>();
        mapVal.put("spring", "春");
        mapVal.put("summer", "夏");
        mapVal.put("autumn", "秋");
        mapVal.put("winter", "冬");
        //获取mapVal集合的所有key值
        Set<String> set = mapVal.keySet();
        Iterator<String> it = set.iterator();
        while(it.hasNext()){
            String season = it.next();
            System.out.println(season);
        }
    }
}

  不仅如此,Map里key集合和Set集合里元素的存储形式也很像,Map子类和Set子类在名字上也惊人的相似:如Set接口下有HashSet、LinkedHashSet、SortedSet(接口)、TreeSet、EnumSet等实现类和子接口,而Map接口下则有HashMap、LinkedHashMap、SortedMap(接口)、TreeMap、EnumMap等实现类和子接口。正如它们名字所暗示的,Map的这些实现类和子接口中key集存储形式和对应Set集合中元素的存储形式完全相同。

  如果把Map所有value放在一起看,它们又非常类似于一个List:元素与元素之间可以重复,每个元素可以根据索引来查找,只是map中的索引不再使用整数值,而是以另一个对象做为索引。如果需要从List集合中取元素,需要提供该元素的数字索引;如果需要从Map中取出元素,需要提供该元素的key索引。因此,Map有时也被称为字典,或关联数组。Map接口中定义了如下常用方法:

  1. void clear();  //删除该Map对象中所有key-value对。
  2. boolean containsKey(Object key);        //查询Map中是否包含指定key,如果包含则返回true。
  3. boolean containsValue(Object value);   //查询Map中是否包含一个或多个value,如果包含则返回true。
  4. Set entrySet();        //返回Map中所包含的key-value对所组成的Set集合,每个集合元素都是Map.Entry(Entry是Map的内部类)对象。
  5. Object get(Object key);        //返回指定key所对应的value,如果此Map不包含该key,则返回null。
  6. boolean isEmpty();            //查询该Map集合是否为空(即不包含任何key-value对),如果为空则返回true。
  7. Set keySet();      //返回该Map中所有key所组成的Set集合。
  8. Object put(Object key, Object value);       //添加一个key-value对,如果当前Map中已有一个与key相等的key-value对,则新的key-value对会覆盖原来的key-value对。
  9. void putAll(Map m);        //将指定Map中的key-value对复制到本Map中。
  10. Object remove(Object key);        //删除指定key所对应的key-value对,返回被删除key所关联的value,如果key不存在,返回nul
  11. int size();            //返回该Map里的key-value对的个数。
  12. Collection values();     //返回该Map里所有value组成的Collection。

  Map中包含一个内部类:Entry。该类封装了一个key-value对,Entry包含三个方法:

    1. Object  getKey();  //返回该Entry里包含的key值。
    2. Object  getValue();   //返回该Entry里包含的value值。
    3. Object  setValue(V value);  //设置该Entry里包含的value值,并返回新设置的value值。

 我们可以把Map理解成一个特殊的Set,只是该Set里包含的集合元素是Entry对象,而不是普通对象。

如下为Entry示例:

public class Test {
    public static void main(String[] args){
        Map<String, String> mapVal = new HashMap<String, String>();
        mapVal.put("spring", "春");
        mapVal.put("summer", "夏");
        mapVal.put("autumn", "秋");
        mapVal.put("winter", "冬");
        Set<Entry<String, String>> entrySet = mapVal.entrySet();
        Iterator<Entry<String, String>> iterator = entrySet.iterator();
        while(iterator.hasNext()){
            Entry<String, String> next = iterator.next();
            String key = next.getKey();
            String value = next.getValue();
            System.out.println("key:"+ key +"-------value:" + value);
        }
    }
}

  • HashMap和Hashtable实现类

  HashMap和Hashtable都是Map接口的典型实现类,他们之间的关系完全类似于ArrayList和Vector的关系:Hashtable是一个古老的Map实现类,它从JDK1.0起就已经出现了,当它出现时,Java没有提供Map接口,所以它包含了两个繁琐的方法:elements()(类似于Map接口定义的values()方法)和keys(类似于Map接口定义的keySet()方法),现在很少使用这两个方法。

  HashMap和Hashtable的两点典型区别:

    Hashtable是一个线程安全的Map实现,但HashMap是线程不安全的实现,所以HashMap比Hashtable性能要高一点;但如果有多条线程访问同一个Map对象时,使用Hashtable实现类会更好。

    Hashtable不容许使用null作为key和value,如果试图把null放进Hashtable中,将会引发NullPointerException异常;但HashMap可以使用null做为key和value。

  注意:与Vector类似,尽量少用Hashtable实现类,即使需要创建线程安全的Map实现类,也可以通过Collections工具类把HashMap变成线程安全的,无须使用Hashtable实现类。

    为了成功地在HashMap、Hashtable中存储、获取对象,用作key的对象必须实现hashCode方法和equals方法。

    与HashSet不能保证元素的顺序一样,HashMap和Hashtable也不能保证key-value对的顺序。类似于HashSet的是,HashMap、Hashtable判断两个key相等的标准也是:两个key通过equals方法比较返回true,两个key的   hashCode值也相等。

    除此之外,HashMap、Hashtable中还包含一个containsValue方法用于判断是否包含指定的value,那么HashMap、Hashtable如何判断两个value相等呢?HashMap、Hashtable判断两个value相等的标准更简单:只要两个对象通过equals比较返回true即可。

  • LinkedHashMap类  

  HashMap有一个子类:LinkedHashMap;LinkedHashMap也使用双向链表来维护key-value对的次序,该链表定义了迭代顺序,该迭代顺序与key-value对的插入顺序保持一致。LinkedHashMap可以避免需要对HashMap、Hashtable里的key-value对进行排序(只要插入key-value对时保持顺序即可)。同时又避免使用TreeMap所增加的成本。

   LinkedHashMap需要维护元素的插入顺序,因此性能略低于HashMap的性能,但在迭代访问Map里的全部元素时将有很好的性能,因为它以链表来维护内部顺序。

public class Test {
    public static void main(String[] args){
        LinkedHashMap<String, String> mapVal = new LinkedHashMap<String, String>();
        mapVal.put("spring", "春");
        mapVal.put("summer", "夏");
        mapVal.put("autumn", "秋");
        mapVal.put("winter", "冬");
        System.out.println(mapVal);
        for(String str : mapVal.keySet()){
            System.out.println("key:" + str);
            System.out.println("value:" + mapVal.get(str));
        }
    }
}

  • Properties类

    Properties类是Hashtable类的子类,正如它的名字所暗示的,该文件在处理属性文件。 Properties类可以把Map对象和属性文件关联起来,从而可以把Map对象中的key-value对写入属性文件,也可以把属性文件中的属性名=属性值加载到Map对象中。由于属性文件里的属性名、属性值只能是字符串类型,所以Properties里的key、value都是字符串类型,该类提供了如下三个方法来修改Properties里的key、value值。

    1. String  getProperty(String key);   //获取properties中指定属性名对应的属性值,类似于Map的get(Object key)方法。
    2. String  getProperty(String key, String defaultValue);    //该方法与前一个方法基本相似,该方法多个功能,如果Properties中不存在指定key时,该方法返回默认值。
    3. Object setProperty(String  key, String value);    //设置属性值,类似Hashtable的put方法。
    4. void load(InputStream inStream);      //从属性文件(以输出流表示)中加载属性名=属性值,把加载到的属性名=属性值对追加到Properties里(由于Properties是Hashtable的之类,它不保证key-value对之间的次序)。
    5. void store(OutputStream out, String comments);    //将Properties中的key-value对写入指定属性文件(以输出流表示),comments是要写的注解。

   如下代码所示:

public class Test {
    public static void main(String[] args){
        Properties readProperties = new Properties();  //用来写的Properties对象
        readProperties.setProperty("username", "zhangsan");
        readProperties.setProperty("password", "123456");
        Properties writeProperties = new Properties(); //用来读的Properties对象
        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;
        try {
            //1.1通过类装载器获取要存储的路径
            String path = Test.class.getResource("/").getPath();
                path = path +  "config.properties";
            System.out.println(path);
            fileOutputStream = new FileOutputStream(new File(path));
            //1.2将配置文件信息写到硬盘上
            readProperties.store(fileOutputStream, "This is config with database!");

            //2.1读取硬盘上的配置文件
            fileInputStream = new FileInputStream(new File(path));
            writeProperties.load(fileInputStream);
            String username = writeProperties.getProperty("username");
            String username2 = writeProperties.getProperty("username2" , "没有找到username2的key");
            //打印结果"sername:zhangsan"
            System.out.println("username:" + username);
            //打印结果"username2:没有找到username2的key"
            System.out.println("username2:" + username2);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(fileOutputStream != null){
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

  • SortedMap接口和TreeMap实现类

  正如Set接口派生出了SortedSet子接口,SortedSet接口有一个TreeSet实现类,Map接口也派生了一个SortedMap子接口,SortedMap也有一个TreeMap实现类。

  与TreeSet类似的是,TreeMap也是基于红黑树对TreeMap中所有key进行排序,从而保证TreeMap中所有key-value对处于有序状态。TreeMap也有两种排序方式:

    自然排序:TreeMap的所有key必须实习那Comparable接口,而且所有key应该是同一个类的对象,否则将会抛出ClassCaseException。

    定制排序:创建TreeMap时,传入一个Comparator对象,该对象负责对TreeMap中所有key进行排序。采用定制排序时不要求Map的key实现Comparable接口。

  *可以参考TreeSet的代码演示。

  • WeakHashMap实现类

  WeakHashMap与HashMap的用法基本相似。但与HashMap的区别在于,HashMap的key保留对象的强引用,这意味着只要该HashMap对象不被销毁,该HashMap对象所有key所引用的对象不会被垃圾回收,HashMap也不会自动删除这些key所对应的key-value对象;但WeakHashMap的key只保留对实际对象的弱引用,这意味着当垃圾回收了该key所对应的实际对象后,WeakHashMap会自动删除该key对应的key-value对。

  

public class Test {
    public static void main(String[] args){
        WeakHashMap<String, String> map = new WeakHashMap<String, String>();
            //将WeakHashMap中添加三个key-value对,
            //三个key都是匿名字符串对象(没有其他引用)
            map.put(new String("语文"), new String("优"));
            map.put(new String("数学"), new String("良"));
            map.put(new String("英语"), new String("中"));
            //将WeakHashMap中添加一个key-value对,
            //该key是一个系统缓存的字符串对象。
            map.put("java", new String("不及格"));
            //输出map对象,将看到4个key-value对{java=不及格, 数学=良, 英语=中, 语文=优}
            System.out.println(map);
            //通知系统立即进行垃圾回收
            System.gc();
            System.runFinalization();
            //通常情况下,将只看到一个key-value对{java=不及格}
            System.out.println(map);
    }
}

  从上面运行结果可以看出,当系统进行垃圾回收时,删除了WeakHashMap对象的前三个key-value对。这是因为添加前三个key-value对时,这三个key都是匿名字符串对象,只有WeakHashMap保留了对它们的弱引用。WeakHashMap对象中的第四组key-value对的key是一个字符串的直接量,系统会缓冲这个字符串直接量(即系统保留了对该字符串对象的强引用),所以垃圾回收时不会回收它。

  • IdentityHashMap实现类

  IdentityHashMap实现类的实现机制与HashMap基本相似,但它在处理两个key相等时,比较独特:在IdentityHashMap中,当且仅当两个key严格相等时(key1 = key2)时,IdentityHashMap才认为两个key相等,对于普通HashMap而言,只要key1和key2通过equals比较返回true,且它们的hashCode值相等即可。

  IdentityHashMap提供了与HashMap基本相似的方法,也允许使用null做为key和value。与HashMap类似的是,IdentityHashMap不保证任何key-value对之间的顺序,更不能保证它们的顺序随时间的推移保持不变。

public class Test {
    public static void main(String[] args){
        IdentityHashMap<String, String> map = new IdentityHashMap<String, String>();
            //下面两行代码会向map中添加两条key-value对
            map.put(new String("语文"), "99");
            map.put(new String("语文"), "100");
            //下面两行代码会向map中添加一条key-value对
            map.put("java", "89");
            map.put("java", "69");
            //打印结果为{java=69, 语文=100, 语文=99}
            System.out.println(map);
    }
}

  • EnumMap实现类

  EnumMap是一个与枚举类一起使用的Map实现,EnumMap中所有key都必须是单个枚举类的枚举值。创建EnumMap时必须显示或隐式指定它对应的枚举类。

  EnumMap不允许使用null作为key值,但容许使用null值做为value。如果试图使用null做为key将抛出NullPointerException异常。如果仅仅只是查询是否包含值为null的key,或者仅仅只是使用删除值为null的key,都不会抛出异常。

enum Season{
    SPRING,SUMMER,AUTUMN,WINTER
}
public class Test {
    public static void main(String[] args){
        EnumMap<Season, String> map = new EnumMap<Season, String>(Season.class);
        //打印结果为{}
        System.out.println(map);
        map.put(Season.SPRING, "春");
        map.put(Season.SUMMER, "夏");
        map.put(Season.AUTUMN, "秋");
        map.put(Season.WINTER, "冬");
        //打印结果为{SPRING=春, SUMMER=夏, AUTUMN=秋, WINTER=冬}
        System.out.println(map);
    }
}

  上面程序中创建了一个EnumMap对象,创建该EnumMap对象时指定它的key只能是Season枚举类的枚举值。如果向该EnumMap中添加四个key-value对后,这四个key-value对将会以Season枚举值的自然顺序排序。

  对于Map的常用实现类而言,HashMap和Hashtable的效率大致相同,因为它们的实现机制几乎完全一样,但HashMap通常比Hashtable要快一点,因为Hashtable额外实现同步操作。

  TreeMap通常比HashMap、Hashtable要慢(尤其在插入、删除key-value对的时候更慢),因为TreeMap需要额外的红黑树操作来维护key之间的次序。但使用TreeMap有一个好处:TreeMap中的key-value对总是处于有序状态,无须专门进行排序操作。  

         

    

原文地址:https://www.cnblogs.com/jpfss/p/9772848.html

时间: 2024-10-07 05:29:48

Java中的集合Map、HashMap、Hashtable、Properties、SortedMap、TreeMap、WeakHashMap、IdentityHashMap、EnumMap(五)的相关文章

Java中的集合框架-Map

前两篇<Java中的集合框架-Commection(一)>和<Java中的集合框架-Commection(二)>把集合框架中的Collection开发常用知识点作了一下记录,从本篇开始,对集合框架里的另外一部分Map作一下记录. 一,集合框架的Map接口 Map与Collection不同之处在于它是以键值对来存储数据: Map比较常用的实现类有四个:HashTable,HashMap,LinkedHashMap,TreeMap: Map的方法也可以分为四类,增删改查,大致如下: 新

Java 中的集合接口——List、Set、Map

Java 中的集合接口——List.Set.Map 什么叫集合:集合就是Java API所提供的一系列类的实例,可以用于动态存放多个对象.这跟我们学过的数组差不多,那为什么我们还要学集合,我们看看数组跟集合有什么区别: 数组:长度固定,遍历速度快 可以存储基本类型和引用类型: 集合:长度不固定,只能存储引用类型对象: 从数组跟集合的特点我们很明显的看出,数组有一定的局限性,如果我们需要不定期的往我们的数据中存储数据,数组就满足不了我们的要求. Java集合框架提供了一套性能优良.使用方便的接口和

JAVA中List、Map、Set的区别与选用

类层次关系如下: Collection ├List│├LinkedList│├ArrayList│└Vector│ └Stack└SetMap├Hashtable├HashMap └WeakHashMap 下面来分别介绍 Collection接口 Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements).一些 Collection允许相同的元素而另一些不行.一些能排序而另一些不行.Java SDK不提供直接继承自Col

Java中List Set Map 是否有序等总结

1.Collection List Set Map 区别记忆 这些都代表了Java中的集合,这里主要从其元素是否有序,是否可重复来进行区别记忆,以便恰当地使用,当然还存在同步方面的差异,见上一篇相关文章. 有序否 允许元素重复否 Collection 否 是 List 是 是 Set AbstractSet 否 否 HashSet TreeSet 是(用二叉树排序) Map AbstractMap 否 使用key-value来映射和存储数据,Key必须惟一,value可以重复 HashMap T

java中各种集合的用法和比较

一,java中各种集合的关系图 Collection       接口的接口     对象的集合 ├ List             子接口         按进入先后有序保存   可重复 │├ LinkedList    接口实现类     链表     插入删除   没有同步   线程不安全 │├ ArrayList     接口实现类      数组     随机访问   没有同步   线程不安全 │└ Vector        接口实现类       数组              

JAVA笔记整理(九),JAVA中的集合

在工作中,我们经常需要将多个对象集中存放,可以使用数组,但是数组的长度一旦固定之后是不可变的,为了保存数量确定的数据,我们可以使用JAVA中的集合. 在我看来,JAVA中的集合可以看作是一个特殊的数据库,可以针对这个数据库进行数据的增删查改,可以查看数据库的大小,查看数据库是否为空等等. JAVA中的集合是由Collection和Map两个接口派生出来的,正因为是两个接口,所以只能通过其子类来将其实例化,下图为常用集合: Collection是List.Queue和Set接口的父接口,Map是H

java中的集合框架

由于数组具有属性单一,长度不可改变的缺点,于是在程序中我们使用集合来代替它. 集合中不可放入基本数据类型,基本数据类型都是通过自动拆包和自动装箱功能才能放入和取出集合. 分类:Collection接口和Map接口 Collection:存放单一值元素,又可分为list接口类型和set接口类型 list接口类型:存放元素是有序的可重复的,可通过循环来取出其中的元素,实现类ArrayList() set接口类型:hash值排列,存放元素是无序不可重复的,通过指针取出其中元素,实现类HashSet()

转!! Java中如何遍历Map对象的4种方法

在Java中如何遍历Map对象 How to Iterate Over a Map in Java 在java中遍历Map有不少的方法.我们看一下最常用的方法及其优缺点. 既然java中的所有map都实现了Map接口,以下方法适用于任何map实现(HashMap, TreeMap, LinkedHashMap, Hashtable, 等等) 方法一 在for-each循环中使用entries来遍历 这是最常见的并且在大多数情况下也是最可取的遍历方式.在键值都需要时使用. [java] view

Collections+Iterator 接口 | Map+HashMap+HashTable+TreeMap |

Collections+Iterator 接口 1. Collections 是一个操作 Set.List 和 Map 等集合的工具类 Collections 中提供了大量方法对集合元素进行排序.查询和修改等操作,还提供了对集合对象设置不可变.对集合对象实现同步控制等方法 排序操作: reverse(List):反转 List 中元素的顺序 shuffle(List):对 List 集合元素进行随机排序 sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序 sort(Li