集合框架之Map接口

Map是将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。

Map 接口提供三种collection视图,允许以键集、值集或键-值映射关系集的形式查看某个映射的内容。映射顺序定义为迭代器在映射的 collection 视图上返回其元素的顺序。某些映射实现可明确保证其顺序,如 TreeMap 类;另一些映射实现则不保证顺序,如 HashMap 类。

所有通用的映射实现类应该提供两个“标准的”构造方法:一个 void(无参数)构造方法,用于创建空映射;一个是带有单个 Map 类型参数的构造方法,用于创建一个与其参数具有相同键-值映射关系的新映射。实际上,后一个构造方法允许用户复制任意映射,生成所需类的一个等价映射。尽管无法强制执行此建议(因为接口不能包含构造方法),但是 JDK 中所有通用的映射实现都遵从它。

Map接口的方法列表如下:

void clear()

从此映射中移除所有映射关系(可选操作)。

boolean containsKey(Object key)

如果此映射包含指定键的映射关系,则返回true。

boolean containsValue(Object value)

如果此映射将一个或多个键映射到指定值,则返回 true。

Set<Map.Entry<K,V>> entrySet()

返回此映射中包含的映射关系的 Set 视图。

boolean equals(Object o)

比较指定的对象与此映射是否相等。

V get(Object key)

返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。

int hashCode()

返回此映射的哈希码值。

boolean isEmpty()

如果此映射未包含键-值映射关系,则返回true。

Set<K> keySet()

返回此映射中包含的键的 Set 视图。

V put(K key, V value)

将指定的值与此映射中的指定键关联(可选操作)。

void putAll(Map<? extends K,? extends V>m)

从指定映射中将所有映射关系复制到此映射中(可选操作)。

V remove(Object key)

如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。

int size()

返回此映射中的键-值映射关系数。

Collection<V> values()

返回此映射中包含的值的Collection 视图。

Map有三个通用实现类:HashMapTreeMapLinkedHashMap,它们的行为及性能上的对比,可以参照Set接口中的HashSet,TreeSet,LinkedHashSet,十分类似

下面我们通过三个实例来看一下这三种实现类的区别:

         String[] message = {"if", "it", "is", "to","be", "it", "is", "up", "to","me", "to", "delegate"};
         Map<String,Integer> map = newHashMap<String,Integer>();
             for(String str : message){
                    Integer freq = map.get(str);
                    map.put(str, freq == null ? 1 : freq+1);
             }
             System.out.println("单词总数:"+map.size());
             System.out.println(map);

控制台输出:

单词总数:8

{to=3, is=2,it=2, if=1, me=1, delegate=1, up=1, be=1}

该实例使用HashMap作为容器,形成单词和词频的映射

假如我们想让Map中的元素按照字母顺序排序,把实现类换成TreeMap即可{"if", "it", "is", "to","be", "it

String [] message = {"if", "it", "is", "to","be", "it", "is", "up", "to","me", "to", "delegate"};
Map<String,Integer> map = new TreeMap<String,Integer>();
             for(String str : message){
                    Integer freq = map.get(str);
                    map.put(str, freq == null ? 1 : freq+1);
             }
             System.out.println("单词总数:"+map.size());
             System.out.println(map);

控制台输出:

单词总数:8

{be=1, delegate=1, if=1, is=2,it=2, me=1, to=3, up=1}

类似地,如果我们想让打印结果按照单词第一次出现的顺序排序,将实现类改成LinkedHashMap即可

String [] message = {"if", "it", "is", "to","be", "it", "is", "up", "to","me", "to", "delegate"};
             Map<String,Integer> map = newTreeMap<String,Integer>();
             for(String str : message){
                    Integer freq = map.get(str);
                    map.put(str, freq == null ?1 : freq+1);
             }
             System.out.println("单词总数:"+map.size());
             System.out.println(map);

控制台输出:

单词总数:8

{if=1, it=2,is=2, to=3, be=1, up=1, me=1, delegate=1}

在上面的三个实例中,我们只改变了实现类的名称,其他代码一点都没做改动,就达到了想要的效果,这就是面向接口编程赋予程序的弹性。

Map提供了三种转换为Collection视图(可以将Map当做Collection来看)的方法:

keySet():Map中的键Set型集合

values():Map中的值Collection集合,不能为Set,值集合中可能会有重复值

entrySet():Map中的键值对Set型集合

Map的Collection视图提供了唯一的Map的迭代方法。Map并没有提供返回Iterator迭代器的方法,只能借助于Collection视图的迭代器来遍历Map

需要注意的是,entrySet()返回的Set里面的元素是Map.Entry<K,V>,该接口提供了一些方法来操作键值对,方法列表如下:

boolean equals(Object o)

比较指定对象与此项的相等性。

K getKey()

返回与此项对应的键。

V getValue()

返回与此项对应的值。

int hashCode()

返回此映射项的哈希码值。

V setValue(V value)

用指定的值替换与此项对应的值(可选操作)。

Map.entrySet 方法返回映射的collection 视图,其中的元素属于此类。获得映射项引用的唯一方法是通过此collection 视图的迭代器来实现。这些Map.Entry 对象仅在迭代期间有效;更确切地讲,如果在迭代器返回项之后修改了底层映射,则某些映射项的行为是不确定的,除了通过 setValue 在映射项上执行操作之外。

下面给出具体的实例:

String [] message = {"if", "it", "is", "to","be", "it", "is", "up", "to","me", "to", "delegate"};
             Map<String,Integer> map = newHashMap<String,Integer>();
             for(String str : message){
                    Integer freq = map.get(str);
                    map.put(str, freq == null ?1 : freq+1);
             }

             for(String key : map.keySet()){
                    System.out.println(key+"——》"+map.get(key));
             }

该实例通过遍历键集合打印出所有的键值对

还可以通过遍历entrySet集合实现上面的过程,下面的代码与上面的for-each循环是等价的

for(Map.Entry<String,Integer>entry : map.entrySet()){
                    System.out.println(entry.getKey()+"——》"+entry.getValue());
             }

HashMap

基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。(除了非同步和允许使用null 之外,HashMap 类与 Hashtable 大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。

HashMap 的实例有两个参数影响其性能:初始容量加载因子。容量是哈希表中桶的数量,初始容量只是哈希表在创建时的容量。加载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。

通常,默认加载因子 (0.75) 在时间和空间成本上寻求一种折衷。加载因子过高虽然减少了空间开销,但同时也增加了查询成本(在大多数 HashMap 类的操作中,包括 get 和 put 操作,都反映了这一点)。在设置初始容量时应该考虑到映射中所需的条目数及其加载因子,以便最大限度地减少 rehash 操作次数。如果初始容量大于最大条目数除以加载因子,则不会发生 rehash 操作。

如果很多映射关系要存储在 HashMap 实例中,则相对于按需执行自动的 rehash 操作以增大表的容量来说,使用足够大的初始容量创建它将使得映射关系能更有效地存储。

扩展的构造方法(即除了Map实现类都有的一个无参的构造方法和一个以Map为参数的构造方法之外,自身独有的构造方法)

Hashtable(intinitialCapacity)

用指定初始容量和默认的加载因子(0.75) 构造一个新的空哈希表。

Hashtable(intinitialCapacity, float loadFactor)

用指定初始容量和指定加载因子构造一个新的空哈希表。 HashMap实现了Map接口的所有方法,没有自身特有的扩展方法

TreeMap

基于红黑树(Red-Black tree)同时继承了NavigableMap接口的实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。

注意,如果要正确实现 Map 接口,则有序映射所保持的顺序(无论是否明确提供了比较器)都必须与 equals 一致。(关于与 equals 一致的精确定义,请参阅 Comparable 或 Comparator)。这是因为 Map 接口是按照 equals 操作定义的,但有序映射使用它的 compareTo(或 compare)方法对所有键进行比较,因此从有序映射的观点来看,此方法认为相等的两个键就是相等的。即使排序与 equals 不一致,有序映射的行为仍然是定义良好的,只不过没有遵守 Map 接口的常规协定。

TreeMap的扩展的构造方法:

TreeMap(Comparator<?super K> comparator)

构造一个新的、空的树映射,该映射根据给定比较器进行排序。

TreeMap(SortedMap<K,?extends V> m)

构造一个与指定有序映射具有相同映射关系和相同排序顺序的新的树映射。

扩展的方法:

Comparator<?super K> comparator()

返回对此映射中的键进行排序的比较器;如果此映射使用键的自然顺序,则返回 null。

NavigableSet<K> descendingKeySet()

返回此映射中所包含键的逆序NavigableSet 视图。

NavigableMap<K,V> descendingMap()

返回此映射中所包含映射关系的逆序视图。

Map.Entry<K,V> firstEntry()

返回一个与此映射中的最小键关联的键-值映射关系;如果映射为空,则返回 null。

K firstKey()

返回此映射中当前第一个(最低)键。

Map.Entry<K,V> floorEntry(K key)

返回一个键-值映射关系,它与小于等于给定键的最大键关联;如果不存在这样的键,则返回 null。

K floorKey(K key)

返回小于等于给定键的最大键;如果不存在这样的键,则返回 null。

SortedMap<K,V> headMap(K toKey)

返回此映射的部分视图,其键值严格小于toKey。

NavigableMap<K,V> headMap(K toKey,boolean inclusive)

返回此映射的部分视图,其键小于(或等于,如果 inclusive 为 true)toKey。

Map.Entry<K,V> higherEntry(K key)

返回一个键-值映射关系,它与严格大于给定键的最小键关联;如果不存在这样的键,则返回 null。

K higherKey(K key)

返回严格大于给定键的最小键;如果不存在这样的键,则返回 null。

Map.Entry<K,V> lastEntry()

返回与此映射中的最大键关联的键-值映射关系;如果映射为空,则返回 null。

K lastKey()

返回映射中当前最后一个(最高)键。

Map.Entry<K,V> lowerEntry(K key)

返回一个键-值映射关系,它与严格小于给定键的最大键关联;如果不存在这样的键,则返回 null。

K lowerKey(K key)

返回严格小于给定键的最大键;如果不存在这样的键,则返回 null。

NavigableSet<K> navigableKeySet()

返回此映射中所包含键的NavigableSet 视图。

Map.Entry<K,V> pollFirstEntry()

移除并返回与此映射中的最小键关联的键-值映射关系;如果映射为空,则返回 null。

Map.Entry<K,V> pollLastEntry()

移除并返回与此映射中的最大键关联的键-值映射关系;如果映射为空,则返回 null。

NavigableMap<K,V> subMap(K fromKey,boolean fromInclusive, K toKey, boolean toInclusive)

返回此映射的部分视图,其键的范围从fromKey 到 toKey。

SortedMap<K,V> subMap(K fromKey, K toKey)

返回此映射的部分视图,其键值的范围从fromKey(包括)到 toKey(不包括)。

SortedMap<K,V> tailMap(K fromKey)

返回此映射的部分视图,其键大于等于fromKey。

NavigableMap<K,V> tailMap(K fromKey,boolean inclusive)

返回此映射的部分视图,其键大于(或等于,如果 inclusive 为 true)fromKey。

LinkedHashMap

Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。此实现与 HashMap 的不同之处在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序通常就是将键插入到映射中的顺序(插入顺序)。注意,如果在映射中重新插入键,则插入顺序不受影响。(如果在调用 m.put(k, v) 前 m.containsKey(k) 返回了 true,则调用时会将键 k 重新插入到映射 m 中。)

可以重写 removeEldestEntry(Map.Entry)方法来实施策略,以便在将新映射关系添加到映射时自动移除旧的映射关系。

此类提供所有可选的 Map 操作,并且允许 null 元素。与 HashMap 一样

扩展的构造方法:

LinkedHashMap(intinitialCapacity)

构造一个带指定初始容量和默认加载因子(0.75) 的空插入顺序 LinkedHashMap 实例。

LinkedHashMap(intinitialCapacity, float loadFactor)

构造一个带指定初始容量和加载因子的空插入顺序 LinkedHashMap 实例。

LinkedHashMap(intinitialCapacity, float loadFactor, boolean accessOrder)

构造一个带指定初始容量、加载因子和排序模式的空 LinkedHashMap 实例。

扩展的方法:

protected  boolean removeEldestEntry(Map.Entry<K,V> eldest)

如果此映射移除其最旧的条目,则返回true。

Properties

虽然Properties类是Map的子类,但是它并没有实现Map的方法,它与上面的其他子类有本质的区别,由于在应用中广泛使用property 作为配置文件,在此一并列出并给出代码实例

Properties 类表示了一个持久的属性集。Properties可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串

一个属性列表可包含另一个属性列表作为它的“默认值”;如果未能在原有的属性列表中搜索到属性键,则搜索第二个属性列表。

因为 Properties 继承于 Hashtable,所以可对Properties 对象应用 put 和 putAll 方法。但不建议使用这两个方法,因为它们允许调用者插入其键或值不是 String 的项。相反,应该使用 setProperty 方法。如果在“不安全”的 Properties 对象(即包含非 String 的键或值)上调用 store 或 save 方法,则该调用将失败。类似地,如果在“不安全”的 Properties 对象(即包含非 String 的键)上调用 propertyNames
或 list 方法,则该调用将失败。

此类是线程安全的:多个线程可以共享单个Properties 对象而无需进行外部同步。

load(Reader) /store(Writer, String) 方法按下面所指定的、简单的面向行的格式在基于字符的流中加载和存储属性。除了输入/输出流使用 ISO 8859-1 字符编码外,load(InputStream) / store(OutputStream, String) 方法与load(Reader)/store(Writer, String) 对的工作方式完全相同。可以使用Unicode 转义来编写此编码中无法直接表示的字符;转义序列中只允许单个 ‘u‘ 字符。可使用 native2ascii
工具对属性文件和其他字符编码进行相互转换。

loadFromXML(InputStream)和 storeToXML(OutputStream, String, String) 方法按简单的 XML 格式加载和存储属性。默认使用 UTF-8 字符编码,但如果需要,可以指定某种特定的编码。XML 属性文档具有以下 DOCTYPE 声明:

<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">

注意,导入或导出属性时不访问系统 URI (http://java.sun.com/dtd/properties.dtd);该系统 URI 仅作为一个唯一标识 DTD的字符串:

  <?xml version="1.0"encoding="UTF-8"?>
    <!-- DTD for properties -->
    <!ELEMENT properties ( comment?, entry*) >
    <!ATTLIST properties version CDATA#FIXED "1.0">
    <!ELEMENT comment (#PCDATA) >
    <!ELEMENT entry (#PCDATA) >
    <!ATTLIST entry key CDATA #REQUIRED>

方法列表:

String getProperty(String key)

用指定的键在此属性列表中搜索属性。

String getProperty(String key, StringdefaultValue)

用指定的键在属性列表中搜索属性。

void list(PrintStream out)

将属性列表输出到指定的输出流。

void list(PrintWriter out)

将属性列表输出到指定的输出流。

void load(InputStream inStream)

从输入流中读取属性列表(键和元素对)。

void load(Reader reader)

按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。

void loadFromXML(InputStream in)

将指定输入流中由 XML 文档所表示的所有属性加载到此属性表中。

Enumeration<?> propertyNames()

返回属性列表中所有键的枚举,如果在主属性列表中未找到同名的键,则包括默认属性列表中不同的键。

Object setProperty(String key, String value)

调用 Hashtable 的方法 put。

void store(OutputStream out, String comments)

以适合使用load(InputStream) 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。

void store(Writer writer, String comments)

以适合使用 load(Reader) 方法的格式,将此Properties 表中的属性列表(键和元素对)写入输出字符。

void storeToXML(OutputStream os, Stringcomment)

发出一个表示此表中包含的所有属性的 XML文档。

void storeToXML(OutputStream os, Stringcomment, String encoding)

使用指定的编码发出一个表示此表中包含的所有属性的 XML 文档。

Set<String> stringPropertyNames()

返回此属性列表中的键集,其中该键及其对应值是字符串,如果在主属性列表中未找到同名的键,则还包括默认属性列表中不同的键。

代码实例:

private staticFile filePath = new File("d:\\test.properties");

      //读取所有的属性
      public static void readAllProps(){
             Properties props = newProperties();
             try{
                    InputStream in = newBufferedInputStream(new FileInputStream(filePath));
                    props.load(in);

                    Enumeration en =props.propertyNames();
                    System.out.println("property文件的所有属性如下:");
                    while(en.hasMoreElements()){
                           String key =(String)en.nextElement();
                           String value =props.getProperty(key);
                           System.out.println(key+"= "+value);
                    }
             }catch(Exception e){
                    e.printStackTrace();
             }
      }

      //写入property文件
      public static void writeProperty(Stringkey,String value,String comment){
             Properties props = newProperties();
             try{
                    InputStream in = newBufferedInputStream(new FileInputStream(filePath));
                    props.load(in);
                    OutputStream out = newFileOutputStream(filePath);
                    props.setProperty(key,value);
                    props.store(out,comment);
             }catch(Exception e){
                    e.printStackTrace();
             }
      }

      //根据键来取值
      public static String getPropertyByKey(String key){
             Properties props = newProperties();
             try{
                    InputStream in = newBufferedInputStream(new FileInputStream(filePath));
                    props.load(in);
                    String value =props.getProperty(key);
                    return value;
             }catch(Exception e){
                    e.printStackTrace();
                    return null;
             }
      }

      public static void main(String[] args){
             readAllProps();
             getPropertyByKey("name");
             writeProperty("address","Beijing,China", "My Address");
             readAllProps();
      }
时间: 2024-08-28 00:18:32

集合框架之Map接口的相关文章

Java集合框架中Map接口的使用

在我们常用的Java集合框架接口中,除了前面说过的Collection接口以及他的根接口List接口和Set接口的使用,Map接口也是一个经常使用的接口,和Collection接口不同,Map接口并不是线性的存放对象的引用,Map接口提供了一种映射关系,所有的元素都是以键值对(Entry类型对象实例)的方式存储的,所以能够根据key快速查找value,key是映射关系的索引,value是key所指向的对象,注意,这里的value不是一个数值,而是一个对象的引用,Java集合框架的元素均是指对象!

JavaSE入门学习37:Java集合框架之Map接口及其实现类HashMap和TreeMap

一Map接口 Map接口中的每个成员方法由一个关键字(key)和一个值(value)构成.Map接口不直接继承于Collection接口,因 为它包装的是一组成对的"键-值"对象的集合,而且在Map接口的集合中也不能有重复的key出现,因为每个键只能与 一个成员元素相对应. Map接口定义了存储"键(key)--值(value)映射对"的方法.实现Map接口的类用来存储键值对.Map接口中包含 了一个keySet()方法,用于返回Map中所有key组成的Set集合.

Java集合框架之List接口

在上一篇Java集合框架之Collection接口中我们知道List接口是Collection接口的子接口,List接口对Collection进行了简单的扩充,List接口中的元素的特点为有序,可重复,允许null值,因为List继承了Collection接口,所以继承自Collection接口中的方法不再赘述,从List接口中的方法来看,List接口主要是增加了面向位置的操作,允许在指定位置上对集合中的元素进行操作,同时增加了一个能够双向遍历线性表的新列表迭代器ListIterator.下面介

双列集合框架:Map(个人理解)

双列集合框架:Map1.常用实现类结构|----Map:双列数据,存储key-value对的数据 ---类似于高中的函数:y = f(x)* |----HashMap:作为Map的主要实现类:线程不安全的,效率高:存储null的key和value* |----LinkedHashMap:保证在遍历map元素时,可以照添加的顺序实现遍历.* 原因:在原的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素.* 对于频繁的遍历操作,此类执行效率高于HashMap.* |----Tre

Java中集合框架,Collection接口、Set接口、List接口、Map接口,已经常用的它们的实现类,简单的JDK源码分析底层实现

(一)集合框架: Java语言的设计者对常用的数据结构和算法做了一些规范(接口)和实现(实现接口的类).所有抽象出来的数据结构和操作(算法)统称为集合框架. 程序员在具体应用的时候,不必考虑数据结构和算法实现细节,只需要用这些类创建一些对象,然后直接应用就可以了,这样就大大提高了编程效率. (二)集合框架包含的内容: (三)集合框架的接口(规范)   Collection接口:存储一组不唯一,无序的对象 List接口:存储一组不唯一,有序的对象 Set接口:存储一组唯一,无序的对象 Map接口:

黑马程序员-集合框架(Map和Collections)

--Java培训.Android培训.iOS培训..Net培训.期待与您交流!--- 一.概述 Map是一种存储键值对的存储容器,而且保证键的唯一性.提供一种以"键"标识"值"的数据存储方式.接口形式为:Map<K,V>,其中K是此映射所维护的键的类型,V是映射值的类型.其有两个常用子类,HashMap和TreeMap,另有HashTable与HashMap功能类似,是早期版本.三者特点与不同如下: HashMap:JDK1.2版本出现,底层使用哈希表数

Java基础之集合框架(Collection接口和List接口)

首先我们说说集合有什么作用. 一.集合的作用 1.在类的内部,对数据进行组织: 2.简单而快速的搜索大数量的条目: 3.有的集合接口,提供一系列排列有序的元素,并且可以在序列中间快速的插入或者删除有关元素: 例如:做广播操的时候,可以将学生插入到某排某列,反之也可以叫某排某列中的学生出列. 4.有的集合接口,提供了映射关系,可以通过关键字(key)去快速查找到对应的唯一对象,而这个关键字可以是任意类型. 例如:在吃饭的时候,众多铝饭盒中如何区别是自己的呢?在饭盒上刻独有的标志或贴纸条,这个标志和

Java集合框架中List接口的简单使用

Java集合框架可以简单的理解为一种放置对象的容器,和数学中的集合概念类似,Java中的集合可以存放一系列对象的引用,也可以看做是数组的提升,Java集合类是一种工具类,只有相同类型的对象引用才可以放到同一个集合中,否则是不能放进去的: 集合可以对元素进行简单快速的查找.插入.删除操作 某些集合可以有<key value>映射的关系 数组的长度是固定的,而集合的长度是跟随元素的个数动态变化的,灵活性和扩展性都比数组更加优越 数组只能存放基本类型的数据,而集合存放的是对象引用类型的 数组只能通过

初始集合框架 List Map Set

java集合框架集合框架就是简称JCF(java Collections Framework)集合的特点:元素类型可以不同,集合长度不变,空间不固定 Collection接口和Iterator接口 在集合框架中,分为两种API:一是装载数据的集合类.二是操作集合的工具类. 集合接口位于Set接口和List接口的最顶层,是Set接口和List接口的父接口.定义了Collection对象共有的一些基本方法,这些方法分为基本操作.批量操作和数组操作. Iterator接口是一种用于遍历集合的接口.所谓