Java集合框架(二)

  • Post author:
  • Post category:java




Map接口

Map(映射)接口是Java集合框架中不同于Collection接口的另一个重要接口,它对应的是在一种从键(Key)到值(Value)的对应关系的集合。也就是说,Map类型的对象容器里面保存着两组对象,一组对象用于保存Map里的Key,另外一组用于保存Value。Key和Value可以是任何引用类型的数据。Key不能重复,但是Value可以重复。

Key和Value之间存在单向一对一关系,即通过指定的Key,可以找到唯一对应的Value。也就是说,从Map中取出数据时,只要给出指定的Key,就可以取出对应的Value。

如果把Map中的所有Key放在一起,就组成了一个Set集合(所有Key没有顺序,而且不能重复),实际上Map接口中确实有一个keySet()方法,用于返回Map中所有Key组成的Set对象。而所有Value放在一起,就组成一个可以重复的,没有次序的Collection集合。Map中也提供了一个Values()方法,用于返回Map中所有Value组成的Collection对象。

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

Map接口中定义了Map对象所共有的方法。这些方法基本分为三类操作:基本操作、批量操作、Collection视角的操作。

表15-6  Map类的基本方法



类别



方 法



描  述

基本操作

get( Object key )

返回与指定键相关的值

put(Object key, Object value )

向该映射中添加键值对

remove(Object key)

从该映射中删除包含指定键的键值对

containsKey(Object key )

如果该映射包含指定键,则返回true

containsValue(Object value )

如果该映射包含指定值,则返回true

size()

返回该映射中包含的键/值映射关系数

isEmpty()

如果该映射为空,则返回为true

批量操作

clear()

删除映射内所有元素

putAll(Map m)

将指定映射中的所有映射关系复制到此映射中

Collection

视角操作

keySet()

返回一个包含映射中所有Key的Set对象

values()

返回一个包含映射总所有Value的Collection对象

entrySet()

返回一个包含该Map中所有条目的Set对象,条目由内部接口Entry定义

在Map接口的实现类中,最常用的是HashMap和TreeMap。下面我们分别详细讲述HashMap和TreeMap的用法。




HashMap类


HashMap是基于哈希算法的Map接口的实现。HashMap将它的键保存在哈希表中进行维护,键是唯一的。但是,HashMap并不保证键以特定顺序排列,特别是不保证顺序永久不变。

HashMap类实现了Map接口,从而具有Map接口的所有方法。

为了保证HashMap能正常工作, 和HashSet一样,要求当两个键对象通过equals()方法比较为true时,这两个键对象的hashCode()方法返回的哈希码也一样。因此,我们应该在作为Key的类中重写hashCode()和equals()方法。

HashMap使用哈希码通过键对其内容进行快速查找,但是HashMap中的元素是没有顺序的。如果要让Map中的元素按照一定的顺序排列,就要使用TreeMap类。




TreeMap类


TreeMap类是基于红黑树算法的Map接口实现。TreeMap中键的存放方式与TreeSet相似,它将键存放在树中,键的顺序按照自然顺序或者自定义顺序两种方式排列。

TreeMap类的基本方法与HashMap类相似。



工具类Collections和Arrays

Java集合框架中包含了Collections类和Array类这两个功能强大的工具类,这两个类提供了包装器实现、数据结构算法和数组相关的应用。这两个工具类都提供了大量静态方法,在操作集合和数组时,使用这两个工具类中的方法,可以大大减轻程序员编码量,提升开发效率,提高代码性能。




Collections类


Java集合框架中提供了一个操作Set、List和Map等集合的工具类Collections,该工具类中提供了大量方法,用于对集合元素进行排序、查询、修改等操作。这些方法都是静态方法。

早期Java集合框架中的集合类Vector、Hashtable等都是线程安全的,但是自JDK1.2之后新的集合框架包括(ArrayList、HashSet和HashMap等)都是线程不安全的。如果在程序中有多个线程同时访问新的集合类对象,并且有多个线程试图修改它们,就有可能会出现错误。Collections类中提供了多个静态方法用于创建线程安全的同步集合,包括:

  • synchronizedCollection(Collection c):返回一个线程安全的collection。
  • synchronizedList(List list):返回一个线程安全的list。
  • synchronizedSet(Set s):返回一个线程安全的set。
  • synchronizedMap(Map m):返回一个线程安全的map。




Arrays类


Java集合框架不仅提供了Collections类用于操作集合,同时也提供了Arrays类用于操作数组。Arrays类包含用来操作数组(比如排序和搜索)的各种方法。



    1. 古老的集合类与接口

JDK类库中存在一些在JDK1.0时候就被开发出来的类和接口,后面新版本的JDK出来后,又对这些类或者接口进行了修改,或者重新开发一套来替代。这其中就包括集合类Vector、Hashtable、Stack、Properties类以及遍历器Enumeration接口。

Vector、Hashtable、Stack和Properties类以及Enumeration接口都是很古老的集合类和接口,它们在JDK1.0的时候就出现了,那时候Java还没有提供系统的集合框架。

Vector和Hashtable这两个类都有一些方法名很长的方法。从JDK1.2以后,Java就提供了系统的集合框架。但是已经有很多程序是用Vector和Hashtable来编写的,为了保持向后兼容,同时与现有的集合框架保持一致,Java重新设计了Vector和Hashtable,让二者分别实现List接口和Map接口,同时保留以前的方法,这就造成了这两个类中存在一些功能重复的方法。

Vector(向量)与ArrayList的用法几乎完全相同,二者之间的最大区别在于Vector类是线程安全的,而ArrayList不是。因此,Vector在执行效率上会比ArrayList低。如果在实际应用中,不需要考虑多线程问题,就应该优先考虑使用ArrayList,否则就应该使用Vector。

此外,Vector还提供有一个子类Stack。Stack 类表示后进先出(LIFO)的对象堆栈。它通过五个操作对类Vector进行了扩展,允许将向量视为堆栈。它提供了通常的push()和pop()操作,以及取堆栈顶点的peek()方法、测试堆栈是否为空的empty()方法、在堆栈中查找项并确定到堆栈顶距离的search()方法。 Stack类同样是从JDK1.0时出现的,但是JDK1.6提供的Deque 接口及其实现类提供了 LIFO 堆栈操作的更完整和更一致的set,应该优先使用此set。

同样,Hashtable与HashMap的用法也几乎相同,二者的关系完全类似于Vector与ArrayList的关系。Hashtable是线程安全的,而HashMap不是。因此,HashMap执行效率更佳,如果不考虑线程安全问题,就应该优先考虑HashMap。此外,Hashtable不允许key和value为null,而HashMap是允许的。

Properties类的主要方法包括:

  • String getProperty(String key):根据属性的键key获取属性对应的值。
  • String getProperty(String key, String defaultValue):根据属性的key,获取属性的值。如果没有该key,则返回默认值。
  • Object setProperty(String key, String value):设置属性。
  • void load(InputStream in):从输入流中装载全部属性。
  • void store(OutputSteam out, String comments):将属性内容通过输出流输出。



版权声明:本文为LVwww原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。