标签:
1.1集合简介
在前面学习了Java数组,Java数组的长度是固定的,在同一个数组中只能存放相同类型的数据。数组可以存放基本类型的数据,也可以存放引用类型的数据。
在创建Java数组时,必须明确指定数组的长度。数组一旦创建,其长度就不能被改变。在许多应用中,一组数据的数目是不固定的。比如一个单位的员工数目是变化的。有老员工跳槽,也有新员工进来。
为了使程序能方便地存储和操纵数目不固定的一组数据,JDK类库提供了Java集合,所有Java集合类都位于java.util包中。与Java数组不同,Java集合中不能存放基本数据类型数据,而只能存放对象的引用。
1.1.1. 什么是集合
通常情况下,把具有相同性质的一类东西汇聚成一个整体,就可以成为集合。比如,用Java编程的所有程序员和全体中国人等。通常集合有两种表示方法,一种是列举法,比如集合A={1,2,3,4},另一种是性质描述法,比如集合B={X|0<X<100且X属于整数}。
1.1.2. 什么是集合框架
那么有了集合的概念,什么是集合框架呢?集合框架就是为了表示和操作集合而规定的一种统一的标准的体系结构。任何集合框架都包含三大块内容:对外的接口、接口的实现和对集合运算的算法。
? 接口:即表示集合的抽象数据类型。接口提供了让我们对集合中所表示的内容进行单独操作的可能
? 实现:也就是集合框架中接口的具体实现。实际它们就是那些可复用的数据结构。
? 算法:在一个实现了某个集合框架中的接口的对象上完成某种有用的计算方法,例如查找。排序等。这些算法通常是多态的,因为相同的方法可以再同一个接口被多个类实现时有不同的表现。事实上,算法是可复用的函数。
1.1.3 集合框架的好处
1、它减少了程序设计的辛劳
集合框架通过提供有用的数据结构和算法使我们能集中注意力于重要部分上,而不是为了让程序能正常运转而将注意力集中于底层设计上。通过这些在无关API之间的简易的互用性,使我们免除了为改变对象或转换代码以便联合这些API而去写大量的代码。
2、它提高了程序速度和质量
集合框架通过提供对有用的数据结构和算法的高性能和高质量的实现,这使我们的程序速度和质量得到提高。因为每个接口的实现是可互换的,所以我们的程序可以很容易的通过改变一个实现而进行调整。另外,我们将可以从自己的数据结构的同差事中解脱出来,从而有更多时间关注于程序其他部分的质量和性能。
3、减少去学习和使用新的API的辛劳
许多API有对集合的存储和获取。在过去,这样的API都有一些子API帮助操纵它的集合内容,因此在那些特殊的子API之间就会缺乏一致性,你也不得不从零开始学习,并且在使用时也很容易犯错。而标准集合框架接口的出现使这个问题迎刃而解。
4、减少了设计新API的努力
设计者和实现者不用在每次创建一种依赖于集合内容的API时重新设计,他们只要使用标准集合框架的接口即可。
5、集合框架鼓励软件的复用
对于遵照标准集合框架接口的新的数据结构是可复用的。同样对于操作一个实现了这些接口的对象的算法也是如此。
有了这些优点,并通过合理的使用,它就会成为程序员的一种强大的工具,不过,从历史来看,集合大多其结构相当复杂,也就给它们一个造成极不合理的学习曲线的坏名声。但是,Java的集合框架能缩短我们的学习曲线,从而快速掌握它。
在许多高级语言中的数组其实也是集合的一种简单实现,比如C,C++,Pascal和Java。数组保存着相同类型的多个值,它的长度在数组呗创建时就固定写来,建立之后就无法改变。如果你需要一种大小能动态改变的存储结构,数组就不合适了,这时集合框架就有用武之地了。
1.2 常用的集合接口
1.2.1 集合框架的类图
Java平台提供了一个全新的集合框架。“集合框架”主要由一组用来操作对象的接口组成,不同接口描述一组不同的数据类型。Java集合框架在设计时大量使用了接口和抽象类,这使得集合框架具有良好的扩展性。接口、集合算法和接口是实现是Java集合框架的主要组成部分,Java集合框架如图1-1所示。
图1-1 集合框架图
在很大程度上,一旦理解了接口,我们就理解了框架。虽然我们总要创建接口特定的实现,但访问实际集合的方法应该限制在接口方法的使用上;因此,允许更改基本的数据结构而不必改变其它的代码。
? Collection接口:表示一组对象,这些对象也称为collection的元素。一些collection允许有重复的元素,而另一些则不允许。一些collection是有序的,而另一些则是无序的。
? Set接口继承Collection,但不允许重复,使用自己内部的一个排列机制(无序)。
? List接口继承Collection,允许重复,以元素安插的次序来放置元素,不会重新排列(有序)。
? Map接口是一组成对的键-值对象,即所持有的是key-value对。Map中不能有重复的key。拥有自己的内部排列机制(无序)。
? 容器中的元素类型都为Object。从容器中取得元素时,必须把它转换成原来的类型。
1.2.2 Collection接口
用于表示任何对象或元素组。想要尽可能以常规方式处理一组元素时,就使用这一接口。显然,既然用集合能做这些事情,那么用一个Set或者List同样也能做到。List还增加了一些新的功能,而Map由于不是从集合继承的,所以要单独对待。下面是介绍Collection下的常用方法,见表1-1。
表1-1 集合的常用方法
方法名称 描述
boolean add(Object o) 将对象添加到集合
boolean remove(Object o) 如果集合中有与o相匹配的对象,则删除对象o
int size() 返回当前集合中元素的数量
boolean isEmpty() 判断集合中是否有任何元素
boolean contains(Object o) 查找集合中是否含有对象o
Iterator iterator() 返回一个迭代器,用来访问集合中的各个元素
boolean containsAll(Collection c) 查找集合中是否含有集合c中所有的元素
boolean addAll(Collection c) 将集合c中所有元素添加到该集合
void Clear() 删除集合中所有元素
void removeAll(Collection c) 从集合中删除集合c中的所有元素
void retainAll(Collection c) 从集合中删除集合c不包含的元素
Object[] toArray() 返回一个内含集合所有元素的array
Object[] toArray(Object[] a) 以数组的形式返回集合中与数组a类型匹配的元素
此外,还可以把集合转换成其他任何的对象数组。但是,不能直接把集合转换成原始数据类型的数组,因为集合必须持有对象。
有些方法是可选的。因为实现一个接口必须实现所有接口方法,调用程序就需要一种途径来知道一个可选的方法是不是不受支持。如果调用一种可选方法时,一个UnsupportedOperationException被抛出,则操作失败,因为方法不受支持。此异常类继承RuntimeException类,避免了将所有集合操作放入try-catch块。
Collection不提供get()方法。如果要遍历Collection中的元素,就必须用Iterator(迭代器)。
1.2.3 List
List接口继承了Collection接口以定义一个允许重复项的有序集合。该接口不但能够对列表的一部分进行处理,还添加了面向位置的操作。
另外List实际有两种类型,其中包括最基本的ArrayList,它擅长于对元素的随机访问。以及功能更强大的LinkedList,用它进行随机访问的效率并不高,但它提供的方法要丰富的多。List接口与常用实现类介绍见表1-2。
表1-2 List接口
List接口 顺序是List最重要的特性,它可以保证元素按规定的顺序排列。List为Collection添加了大量的方法,以便我们在List的中部插入和删除元素。只推荐对LinkedList这样做,List也会生产一个ListIterator列表迭代器,利用它可在一个List里朝两个方向巡视,同时插入和删除位于List中部的元素。
ArrayList类 由一个数组实现的List,可对元素进行速度非常快的随机访问。但用它在List中部插入或删除元素的时候速度却比较慢,ListIterator通常只能用于在一个ArrayList中来回“遍历”,而不要用它插入或删除元素。
LinkedList类 提供优化的顺序访问性能,同时可以高效的在List中部进行插入和删除操作,但在进行随机访问时速度却相当慢,此时应换用ArrayList。另外它还提供了addFirst()、addLast()、getFirst()、getLast()、removeFirst()以及removeLast()等方法,这些方法在任何接口或基类中均未定义,适用于对堆栈队列以及双头队列进行操作。
面向位置的操作包括插入某个元素或收集的功能,还包括获取、除去或更改元素的功能。在List中搜索元素可以从列表的头部或尾部开始,如果找到元素,还将报告元素所在的位置。List的常用方法见表1-3.
表1-3 List的常用方法
方法名称 描述
void add(int index,Object element) 在指定位置index上添加元素element
boolean addAll(int index,Collection c) 将集合c的所有元素添加到指定位置index
Object get(int index) 返回List中指定位置的元素
int indexOf(Object o) 返回第一个出现元素o的位置,否则返回-1
int lastIndexOf(Object o) 返回最后一个出现o元素的位置,否则返回-1
Object remove(int index) 删除指定位置上的元素
Object set(int index,Object element) 用元素element取代位置index上的元素,并且返回旧的元素
ListIterator listIterator() 返回一个列表迭代器,用来访问列表中的元素
ListIterator listIterator(int index) 返回一个列表迭代器,用来从指定位置index开始访问列表中的元素
List subList(int fromIndex,int toIndex) 返回从指定位置fromIndex(包含)到toIndex(不包含)范围中的各个列表视图。对子列表的更改(比如add()、remove()、set()调用)对底层List也有影响。
1.2.4 Set
Set接口继承Collection接口,而且它不允许集合中存在重复项,每个具体的Set实现类依赖添加的对象的equals()方法来检查独一性。Set接口没有引入新方法,所以Set就是一个Collection,只不过其行为不同。Set接口及其常用实现类见表1-4.
表 1-4 Set集合
Set接口 添加到Set的每个元素都必须是独一无二的,Set不会添加重复的元素,添加到Set里的对象必须定义equals()以树立对象的“唯一”性。Set拥有与Collection完全相同的接口,Set接口并不保证自己会按任何特定的顺序来容纳元素。
HashSet类 假如在一个Set中的搜索速度是至关重要的,就应考虑用HashSet,同时Object还必须定义hashCode()
TreeSet类 排好序的一种Set,采用树形结构,这样一来就可从Set里提取出一个固定顺序的元素序列。
1.2.5 Map
Map(映射)是一种把键对象和值对象进行映射的集合,它的每一个元素都包含一对键对象和值对象。向Map集合加入元素时,必须提供一对键对象和值对象。从Map集合中检索元素时,只要给出键对象,就会返回值对象。
Map接口不是Collection接口的继承。Map接口用于维护键/值对(key/value)。该接口描述了从不重复的键到值的映射,Map接口及其实现介绍见表1-5。
表 1-5 Map集合
Map接口 维持“键值”对应关系对以便根据一个键查找到相应的值。
HashMap 基于一个散列表实现,用它代替HashTable针对“键值”对的插入和检索。这种形式具有最稳定,但不是最好的性能。可通过构造函数设置散列表的“容量”与“负载比”,从而对性能进行调整
TreeMap 在一个“红黑”树的基础上实现查看键或者“键值”对时,它们会按固定的顺序排列。取决于Comparable或Comparator,稍后即会讲到TreeMap最大的好处就是我们得到的是已排好序的结果。TreeMap是提供了subMap()方法的唯一一种Map,用它可返回树的一部分子映射。
Map接口常用方法见表1-6。
表 1-6 Map集合的常用方法
方法名称 描述
Object put(Object key,Object value) 将互相关联的一个关键字与一个值放入该映像。如果该关键字已经存在,那么与此关键字相关的新值将取代旧值。方法返回关键字的旧值,如果原先不存在,则返回null
Object remove(Object key) 从映像中删除与key相关的映射
void putAll(Map t) 将来自特定映像的所有元素添加到该映像
void clear() 从映像中删除所有映射,键和值都可以为null。但是不能把Map作为一个键或值添加给自身
Object get(Object key) 获得与关键字key相关的值,并且返回与关键字key相关的对象,如果没有在该映像中找到该关键字,则返回null
boolean containsKey(Object key) 判断映像中是否存在关键字key
boolean containsValue(Object value) 判断映像中是否存在值value
int size() 返回当前映像中映射的数量
boolean isEmpty() 判断映像中是否有任何映射
Set KeySet() 返回映像中所有关键字的视图集,因为映射中键的集合必须是唯一的。还可以从视图中删除元素,同时,关键字和它相关的值将从源映像中被删除,但是你不能添加任何元素
Collection values() 返回映像中所有值的视图集,因为映射中值的集合不是唯一的,您用Collection支持。还可以从视图中删除元素,同时,值和它的关键字将从源映像中被删除,但是你不能添加任何元素。
Set entrySet() 返回Map.Entry对象的视图集,即映像中的关键字/值对,因为映射是唯一的,您用Set支持。还可以从视图中删除元素,同时,这些元素将从源映像中被删除,但是不能添加任何元素。
1、Hash表
Hash表是一种数据结构,用来查找对象。Hash表为每个对象计算出一个整数,称为Hash Code(哈希码)。Hash表是个链接式列表的阵列。每个列表称为一个buckets(哈希表元)。对象位置的计算index=HashCode%buckets(HashCode为对象哈希码,buckets为哈希表元总数)。
当添加元素时,有时会遇到已经填充了元素的哈希表元,这种情况称为Hash Collisions(哈希冲突)。这时,就必须判断该元素是否已经存在于该哈希表中。
如果哈希码是合理的随机的分布的,并且哈希表元的数量足够大,那么哈希冲突的数量就会减少。同时,也可以通过设定一个初始的哈希表元数量来更好的控制哈希表的运行。初始哈希表元的数量为buckets=size*150%+1(size为预期元素的数量)。
如果哈希表中的元素放得太满,就必须进行rehashing(再哈希)。再哈希是哈希表元数增倍,并将原有的对象重新导入新的哈希表元中,而原始的哈希表元被删除。Load factor(加载因子)决定何时要对哈希表进行再哈希。在Java编程语言中,加载因子默认值为0.75,默认哈希表元101.
2、Comparable接口和Comparator接口
在“集合框架”中有两种比较接口:Comparable接口和Comparator接口。像String和Integer等Java内建类实现Comparable接口以提供一定排序方式,但这样只能实现该接口一次。对于那些没有实现Comparable接口的类、或者自定义的类,可以通过Comparator接口来定义自己的比较方式。
1.2.6 Iterator
Collection接口的iterator()方法返回一个Iterator。Iterator接口方法能以迭代方式逐个访问集合中各个元素,并安全的从Collection中除去适当的元素。Iterator常用方法见表1-7.
表1-7 Iterator常用方法
方法名称 描述
boolean hasNext() 判断是否存在另一个可访问的元素
Object next() 返回要访问的下一个元素。如果达到集合结尾,则抛出NoSuchElementException异常
void remove() 删除上次访问返回的对象。本方法必须紧跟在一个元素的访问后执行。如果上次访问后集合已被修改,方法将抛出IllegalStateException。Iterator中删除操作对底层Collection也有影响。
迭代器是故障快速修复(fail-fast)的。这意味着,当另一个线程修改底层集合的时候,如果正在用Iterator遍历集合,那么Iterator就会抛出ConcurrentModificationException异常,并立刻执行失败。
1.3 常用集合类
1.3.1 Iterator
Iterator用于对集合容器进行向前的单方向遍历,通常称作迭代器。Iterator模式是用于遍历集合类的标准访问方法。它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免向客户端暴露集合的内部结构。
如何遍历Collection中每一个元素?不论Collection的实际类型如何,它都支持一个iterator()方法,该方法返回一个迭代子,使用该迭代子即可逐一访问Collection中每一个元素。典型的用法如下:
......
Iterator it=Collection.iterator();// 获得一个迭代子
While(it.hasNext()){
Object obj=it.next();//得到下一个元素
}
......
在上面的例子中,我们也可以用Iterator进行迭代。如例1-1所示。
例1-1:
import java.util.*;
public class TestIterator1_1 {
/**
* 这个类演示Iterator的用法
*
* @version 0.1, 31/3/2012
* @author wangsen
*/
public static void main(String[] args) {
List list = new ArrayList();// 创建并初始化一个List数组
// 用add()方法可以将一个对象加入ArrayList数组中
list.add("a");
list.add("b");
list.add("c");
Iterator iter = list.iterator();// 使用iterator()取得元素
while (iter.hasNext()) {// hasNext()是否还有下一个元素
// 使用next()取得下一个元素
System.out.println(iter.next());
}
}
}
执行上面程序运行结果如:
a
b
c
1.3.2 ArrayList类和LinkedList类
在“集合框架”中有两种常规的List实现:ArrayList和LinkedList。使用两种List实现的哪一种取决于我们的需要。如果要支持随机访问,而不必在除尾部的任何位置插入或除去元素,那么,ArrayList提供了可选的集合。但如果要频繁的从列表的中间位置添加和除去元素,而只要顺序的访问列表元素,那么使用LinkedList实现更好。
1、ArrayList类
ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。数组的缺点是每个元素之间不能含有“空隙”,当数组大小不满足时,需要增加存储空间,就要将已有数组数据复制到新的存储空间中。当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制、移动,代价比较高。因此,它适合随机查找和遍历,不适合插入和删除。
ArrayList的实质就是一个自动增长的数组。它是用封装的数组来实现的List接口,底层用数组实现。随着向ArrayList中不断添加元素,其容量会自动增长。
创建一个ArrayList类的实例,可以使用如下构造方法。见表1-8
表 1-8 ArrayList类的构造方法
构造方法 说明
ArrayList() 创建一个空的ArrayList对象
ArrayList(int size) 创建一个指定大小的ArrayList对象
ArrayList(Collection c) 创建指定集合的ArrayList对象
ArrayList类的常用方法见表1-9.
方法 说明
Object[] toArray() 以数组形式返回ArrayList中的元素
int size() 返回当前ArrayList中元素的数量
boolean add(Object o) 将对象添加到ArrayList的最后
boolean add(int index,Object o) 在指定位置上添加o元素
boolean addAll(Collection c) 将集合c中的所有元素添加到ArrayList的最后
Object get(int index) 返回ArrayList中指定位置的元素
int indexOf(Object o) 返回第一个出现元素o 的位置,否则返回-1
int lastIndexOf(Object o) 返回最后一个出现元素o的位置,否则返回-1
Object remove(int index) 删除指定位置上的元素
Object set(int index,Object element) 用元素element取代位置index上的元素,并且返回被取代的元素
Iterator iterator() 返回一个迭代器,用来访问ArrayList中的各个元素
ArrayList类封装了一个动态再分配的Object[]数组。每个ArrayList对象有一个容量。它表示存储列表中元素的数组的容量。当元素添加到ArrayList时,它的容量在常量时间内自动增加。
如例1-2演示ArrayList的部分方法。
例1-2:
import java.util.*;
public class TestArrayList1_2 {
/**
* 这个类演示ArrayList的用法
*
* @version 0.1, 31/3/2012
* @author wangsen
*/
public static void main(String[] args) {
List list = new ArrayList();// 创建并初始化一个List数组
// 用add()方法可以将一个对象加入ArrayList数组中
list.add("a");
list.add("b");
list.add("c");
for(int i=0;i<list.size();i++) {// hasNext()是否还有下一个元素
// 使用next()取得下一个元素
System.out.println(list.get(i));
}
}
}
执行上面程序运行结果如:
a
b
c
ArrayList类的底层是有数组实现的,虽然查询快,但是增、删比较慢。在实际应用中,对于增删比较频繁,而查询比较少时,我们就需要使用LinkedList。
2、LinkedList类
LinkedList类是List接口的另一个重要实现类。它的底层是双向循环链表来实现的,所以便于将新加入的对象插入指定位置。它查询效率低,但是增删效率很高,适用于增删比较频繁,查询次数少的元素集合管理。
创建一个LinkedList类的实例,可以使用如下构造方法。见表1-10.
表1-10 LinkedList类的构造方法
构造方法 说明
LinkedList() 创建一个空的LinkedList对象
LinkedList(Collection c) 创建指定集合的LinkedList对象
LinkedList类添加了一些处理列表两端的方法,见表1-11.
表 1-11 LinkedList类的常用方法
方法名称 说明
boolean add(Object o) 将对象加入到LinkedList对象的最后
void addFirst(Object o) 将对象o添加到列表的开头
int size() 返回当前LinkedList中元素的数量
void addLast(Object o) 将对象o添加到列表的结尾
Object getFirst() 返回列表开头的元素
Object removeFirst() 删除并且返回列表开头的元素
Object getLast() 返回列表结尾的元素
Object removeLast() 删除并且返回列表结尾的元素
使用这些方法,就可以轻松的把LinkedList当做一个堆栈、队列或其它面向端点的数据结构。如例1-3所示。
例1-3:简单的实现先进后出的堆栈类。
import java.util.*;
public class TestLinkedList1_3 {
/**
* 这个类演示LinkedList的用法
*
* @version 0.1, 31/3/2012
* @author wangsen
*/
private LinkedList linkedList = new LinkedList();
public TestLinkedList1_3() {
// 初始化数据
linkedList.add("a");
linkedList.add("b");
linkedList.add("c");
}
public void push(String name) {
// 将元素加入链表前端
linkedList.addFirst(name);
}
public String top() {
// 取得链表的第一个元素
return (String) linkedList.getFirst();
}
public String pop() {
// 移出第一个元素
return (String) linkedList.removeFirst();
}
public boolean isEmpty() {
// 链表是否为空
return linkedList.isEmpty();
}
public static void main(String[] args) {
TestLinkedList1_3 linkList = new TestLinkedList1_3();
System.out.println("修改之前的数据:");
for (int i = 0; i < linkList.linkedList.size(); i++) {
System.out.println(linkList.linkedList.get(i));
}
linkList.push("first");
System.out.println("添加过后的数据:");
for (int i = 0; i < linkList.linkedList.size(); i++) {
System.out.println(linkList.linkedList.get(i));
}
System.out.println("第一个元素为:" + linkList.top());
linkList.pop();// 移除第一个元素
System.out.println("移除第一个元素后的数据:");
for (int i = 0; i < linkList.linkedList.size(); i++) {
System.out.println(linkList.linkedList.get(i));
}
System.out.println("链表为空:" + linkList.isEmpty());
}
}
执行上面程序运行结果如:
修改之前的数据:
a
b
c
添加过后的数据:
first
a
b
c
第一个元素为:first
移除第一个元素后的数据:
a
b
c
链表为空:false
1.3.3 HashSet类和TreeSet类
“集合框架”支持Set接口两种普通的实现:HashSet和TreeSet(TreeSet实现SortedSet接口)。考虑到效率,添加到HashSet的对象需要采用恰当分配哈希码的方式来实现hashCode()方法。
1、HashSet类
HashSet即散列表,按照哈希算法计算出哈希码作为存取和比较的依据,具有很好的存取和查询功能。当向集合中存储对象时,先生成哈希码。如果生成的哈希码与已有对象的哈希码相同,则调用equals()方法对两个对象进行比较;如果哈希码不相等,则根据哈希码在集合中寻找相应的位置来存储对象。HashSet的底层也是由数组实现的,其中的元素按HashCode顺序排列。
HashSet是Set接口实现类中最常用的一个。它通过Hash算法进行存储,所以HashSet具有快速定位元素的特点。
HashSet类的构造方法见表1-12。
表 1-12 HashSet类的构造方法
构造方法 说明
HashSet() 构建一个空的哈希表
HashSet(Collection c) 构建一个哈希集,并且添加集合c中所有元素
HashSet(int size) 构建一个拥有特定容量的空哈希表
HashSet的常用方法见表1-13
表 1-13 HashSet类的常用方法
方法名称 说明
boolean add(Object o) 将对象添加到HashSet
int size() 返回当前HashSet中元素的数据
boolean remove(Object o) 如果HashSet中有与o相匹配的对象,则删除对象
Iterator iterator() 返回一个迭代器,用来访问HashSet中的各个元素
通过下面的例子演示HashSet的用法,如例1-4所示。
例1-4:
import java.util.*;
public class HashSetDemo1_4 {
/**
* 这个类演示HashSet的用法
*
* @version 0.1, 31/3/2012
* @author wangsen
*/
public static void main(String[] args) {
Set set = new HashSet();
set.add("a");
set.add("b");
set.add("c");
set.add("d");
System.out.println("显示数据:");
// 使用Iterator显示对象
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
set.remove("b");// 根据值移除对象
System.out.println("set.remove(b)后的数据为:");
// 使用Iterator显示对象
Iterator iterator1 = set.iterator();
while (iterator1.hasNext()) {
System.out.println(iterator1.next());
}
}
}
执行上面程序运行结果如:
显示数据:
d
b
c
a
set.remove(b)后的数据为:
d
c
a
2、TreeSet类
当要从集合中以有序的方式插入和抽取元素时,就可以使用TreeSet实现。添加到TreeSet的元素必须是可排序的。
TreeSet类的常用方法见表1-14.
表 1-14 TreeSet类的构造方法
方法名称 说明
TreeSet() 构建一个空的树集
TreeSet(Collection c) 构建一个树集,并且添加集合c中所有元素
TreeSet(Comparator c) 构建一个树集,并且使用特定的比较器对其进行排序。Comparator比较器没有任何数据,它只是比较方法的存放器。这种对象有时称为函数对象。函数对象通常在“运行过程中”被定义为匿名内部类的一个实例。
TreeSet(SortedSet s) 构建一个树集,添加有序集合s中所有元素,并且使用与有序集合s相同的比较器排序
下面演示TreeSet的使用方法,如例1-5所示
例1-5:
import java.util.*;
public class TreeSetDemo1_5 {
/**
* 这个类演示TreeSet的用法
*
* @version 0.1, 31/3/2012
* @author wangsen
*/
public static void main(String[] args) {
Set set = new TreeSet();
set.add("a");
set.add("b");
set.add("c");
System.out.println("循环打印输出:");
for (Iterator iter = set.iterator(); iter.hasNext();) {
System.out.println(iter.next());
}
}
}
执行上面程序运行结果如:
循环打印输出:
a
b
c
1.3.4 HashMap类和TreeMap类
集合框架提供两种常规的Map实现:HashMap和TreeMap(TreeMap实现SortedMap接口)。在Map中插入、删除和定位元素,HashMap是最好的选择。但如果要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。使用HashMap要求添加的键类明确定义了hashCode()和equals()的实现。
TreeMap没有调优选项,因为该树总处于平衡状态。
1、HashMap类
HashMap是Map接口的实现类,即是用哈希算法来实现的Map。Map 中只可以存放键值对(key,value),其中key是不可以重复的,key与value是一一对应的。HashMap是非线程安全的容器,允许null的键值对。Key是无序存放且不能重复的,它也是通过哈希码值来保证key不重复的。如果要加入的键值对和HashMap中的键值对的key是相同的,就会将这个集合中的key所对应的value值覆盖。
HashMap类的构造方法见表1-15.
表 1-15 HashMap类的构造方法
构造方法 说明
HashMap() 构建一个空的哈希表
HashMap(Map m) 构建一个哈希映像,并且添加映像m的所有映射
HashMap(int size) 构建一个拥有特定容量的空的哈希映像
HashMap(int size,float load) 构建一个拥有特定容量和加载因子的空的哈希映像
HashMap类的常用方法见表1-16
表1-16 HashMap类的常用方法
方法名称 说明
Object get(Object key) 获得与关键字相关的值,并且返回关键字key相关的对象。如果没有在该映像中找到该关键字,则返回null
Object put(Object key,Object value) 将互相关联的一个关键字与一个值放入该映像。如果该关键字已经存在,那么与此关键字相关的新值将取代旧值。方法返回关键字的旧值,如果关键字原先并不存在,则返回null
int size() 返回当前映像中映射的数量
Object remove(Object key) 从映像中删除与key相关的映射
HashMap实现了Map接口,在内部实现使用哈希算法。下面通过一个示例演示HashMap类的用法,如例1-6所示
例1-6:
import java.util.*;
public class HashMapTest1_6 {
/**
* 这个类演示HashMap的用法
*
* @version 0.1, 31/3/2012
* @author wangsen
*/
public static void main(String[] args) {
HashMap hmap=new HashMap();
hmap.put("key1", "a");
hmap.put("key2", "b");
hmap.put("key3", "c");
//循环遍历数据
for(Iterator i=hmap.keySet().iterator();i.hasNext();){
Object key=i.next();//得到键值
Object value=hmap.get(key);
System.out.print(key+"\t");
System.out.print(value+"\n");
}
}
}
执行上面程序运行结果如:
key3 c
key2 b
key1 a
2、TreeMap类
TreeMap没有调优选项,因为该树总处于平衡状态。TreeMap的常用方法见表1-17.
表1-17 TreeMap的常用方法
方法名称 说明
TreeMap() 构建一个空的映像树
TreeMap(Map m) 构建一个映像树,并且添加映像m中所有元素
TreeMap(Comparator c) 构建一个映像树,并且使用特定的比较器对关键字进行排序
TreeMap(SortedMap s) 构建一个映像树,添加映像树s中所有映射,并且使用与有序映像s相同的比较器排序
下面演示TreeMap类的使用方法,如例1-7所示。
例1-7:
import java.util.*;
public class TreeMapTest1_7 {
/**
* 这个类演示TreeMap的用法
*
* @version 0.1, 31/3/2012
* @author wangsen
*/
public static void main(String[] args) {
TreeMap tm = new TreeMap();
for (int i = 0; i < 10; i++) {
String a = "key" + i;
String b = "value" + i;
tm.put(a, b);// 设置
}
/**
* 使用entrySet()方法生成一个由Map.entry对象组成的Set,
* 而Map.entry对象包括了每个元素的“键”和“值”。这样就可以用iterator了
*
*/
Iterator it = tm.entrySet().iterator();
while (it.hasNext()) {
// entry的输出结果如key0=value0等
Map.Entry entry = (Map.Entry) it.next();
Object key = entry.getKey();
System.out.println(entry);
System.out.println(key);
}
}
}
执行上面程序运行结果如:
key0=value0
key0
key1=value1
key1
key2=value2
key2
key3=value3
key3
key4=value4
key4
key5=value5
key5
key6=value6
key6
key7=value7
key7
key8=value8
key8
key9=value9
key9
﹫总结
本章介绍Java集合框架的应用,主要知识点如下:
? 集合框架就是为表示和操作集合而规定的一种统一的标准的体系结构。
? 集合框架主要由一组用来操作对象的接口组成,不同接口描述一组不同数据类型。其中接口有List接口、Set接口、Map接口和Iterator接口。
? Collection类的对象将多个元素组成一个单元。
? ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。
? LinkedList类是List接口的另一个重要实现类。它的底层是用双向循环链表来实现的,所以便于将新加入的对象插入指定位置。
? HashMap是Map接口的实现类,即是用哈希算法实现的Map。Map中只可以存放键值对(key,value),其中key是不可以重复的,key与value是一一对应的。
﹫作业
1.解释集合与数组的异同
2.创建一个ArrayList对象,并在其中添加一些元素,如aa,bb,cc等。然后对ArrayList进行增、删、改、查。
3.使用HashMap将学生的成绩存入对应的学生中,再全部显示出来。程序输出如下:
刘德华 50
蔡依林 60
成龙 80
【集合】
标签:
原文地址:http://www.cnblogs.com/zuixinxian/p/4839793.html