集合框架概述
引入集合框架
在一个电子宠物系统中,如果想存储多个宠物信息,可以使用数组来实现。但是采用数组存在以下一些明显缺陷。
- 数组长度固定不变,不能很好地适应元素数量动态变化的情况。
- 可通过数组名.length获取数组的长度,却无法直接获取数组中真实存储的狗狗个数。
- 数组采用在内存中分配连续空间的存储方式,根据下标可以快速获取对应的狗狗的信息,但根据狗狗信息查找时效率低下,需要多次比较。在进行频繁插入、删除操作时同时效率低下。
从以上分析可以看出,数组在处理一些问题时存在明显的缺陷,而集合完全弥补了数组的缺陷,它比数组更灵活更实用,可大大提高软件的开发效率,并且不同的集合可适用于不同场合。如果写程序时并不知道程序运行时会需要多少对象,或者需要更复杂的方式存储对象,可以考虑使用Java集合来解决。
Java集合框架包含的内容
Java集合框架为我们提供了一套性能优良、使用方便的接口和类,它们都位于java.util包中。
集合框架是为了表现和操作集合而规定的一种统一的标准结构。集合框架都包含三大块内容:对外接口,接口的实现和对集合运算的算法:
- 接口:表示集合的抽象数据类型,在下图中以虚线框表示,如Collection、List、Set、Map、Iterator
- 实现:集合框架中接口的具体实现,在下图以实线框表示,粗实线框表示最常用的实现,如ArrayList、LinkedList、HashMap、HashSet
- 算法:在一个实现了某个集合框架的接口的对象身上完成某种有用的计算的方法,如查找、排序等。Java提供了进行集合操作的工具类:Collections,它提供了对集合进行排序等多种算法实现。
Java集合框架中的两大类接口:Collection和Map,其中Collection有两个子接口:List和Set。通常说Java集合框架共有三大类接口:List,Set和Map。它们的共同点:都是集合接口,可以用来存储很多对象,它们的区别如下:
- Collection:接口存储一组不唯一,无序的对象
- Set:继承Collection接口,存储一组唯一,无序的对象
- List:继承Collection接口,存储一组不唯一,有序的对象
- Map:存储一组成对的键-值对象,提供key(键)到value(值)的映射。
- Iterator:负责定义访问和遍历元素的接口
List接口
实现List接口常用类有ArrayList和LinkedList。它们可以容纳所有类型的对象,包括null,允许重复,并且都保证元素的存储顺序。
ArrayList对数组进行了封装,实现了长度可变的数组。ArrayList存储数据的方式和数组相同,都是在内存中分配连续的空间,它的优点在于遍历元素和随机访问元素的效率比较高。
常用方法如下:
方法名称 | 说明 |
---|---|
boolean add(Objcet o) | 在列表末尾顺序添加元素,起始索引位置从0开始 |
void add(int index,Object o) | 在指定的索引位置添加元素,原索引位置及其后面的元素依次后移 |
int size() | 返回列表中的元素个数 |
Object get(int index) | 返回指定索引位置处的元素 |
boolean contains(Object o) | 判断列表中是否存在指定元素 |
boolean remove(Object o) | 从列表中删除元素 |
LinkedList采用链表存储方式,优点在于插入、删除元素时效率比较高。它提供了额外的addFirst()、addLast()、removeFirst()和removeLsat()等方法,可以在LinkedList的首部或尾部进行插入或删除操作。这些方法使得LinkedList可被用作堆栈(stack)或者队列(queue)。
常用方法如下:
方法名称 | 说明 |
---|---|
void addFirst(Object o) | 在列表首部添加元素 |
void addLast(Object o) | 在列表末尾添加元素 |
Object getFirst() | 返回列表中第一个元素 |
Object getLast() | 返回列表中最后一个元素 |
Object removeFirst() | 删除并返回列表中的第一个元素 |
object removeLast() | 删除并返回列表中的最后一个元素 |
Map接口
Map接口存储一组成对的键-值对象,提供key(键) 到value(值)的映射,Map中的key不要求有序,不允许重复。value同样不要求有序,但允许重复。最常用的Map实现类是哈希表。哈希表也称为散列表,是根据关键码值(key value)而直接进行访问的数据结构。也就是说,它通过把关键码映射到表中一个位置来访问记录,以加快查找速度。存放记录的数组称为散列表,使用这种方式存储数据的优点是查询指定元素效率高。
常用方法如下:
方法名称 | 说明 |
---|---|
Object put(Object key,Object value) | 以"键-值对"的方式进行存储 注意:键必须是唯一的,值可以重复 |
Object get(Object key) | 根据键返回值,若不存在指定的键,则返回null |
Object remove(Object key) | 删除指定的键映射的"键-值对" |
int size() | 返回元素个数 |
Set keySet() | 返回键的集合 |
Collection values() | 返回值的集合 |
boolean containKey(Object key) | 若存在指定的键映射的"键-值对",则返回true |
boolean isEmpty() | 若不存在键-值映射关系,则返回true |
void clear() | 从此映射中移除所有映射关系 |
HashMap和Hashtable的区别:
- Hasgtable继承自Dictionary类,而HashMap实现了Map接口。
- Hashtable是线程安全的,HashMap是重速度、轻安全,是线程非安全的,所以当运行到多线程环境中时,需要程序员自己管理线程的同步问题。
- Hashtable不允许null值(key和value都不允许),如果存在则运行报错;HashMap允许null值(key和value都允许)。
迭代器Iterator
所有集合接口和类都没有提供相应的遍历方法,而是把遍历交给迭代器Iterator完成。Iterator为集合而生,专门实现集合的遍历。它隐藏了各种集合实现类的内部细节,提供了遍历集合的统一编程接口。
Collection接口的iterator()方法返回一个iterator,然后通过iterator接口的两个方法即可方便地实现遍历。
- boolean hasNext():判断是否存在另一个可访问元素。
- Object next():返回要访问的下一个元素。
Iterator的使用步骤:
- 将集合对象转换为Iterator对象。
- 通过 hasNext()方法进行循环判断。
- 通过next()方法取值。
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class Dog {
public String name;
public String strain;
public Dog(String name,String strain) {
this.name = name;
this.strain = strain;
}
public Dog() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStrain() {
return strain;
}
public void setStrain(String strain) {
this.strain = strain;
}
}
public class Test {
public static void main(String[] args) {
Dog ouoDog = new Dog("欧欧","雪纳瑞");
Dog yayaDog = new Dog("亚亚","拉布拉多");
Dog meimeiDog = new Dog("美美","雪纳瑞");
Dog feifeiDog = new Dog("菲菲","拉布拉多");
Map dogMap = new HashMap();
dogMap.put(ouoDog.getName(),ouoDog);
dogMap.put(yayaDog.getName(),yayaDog);
dogMap.put(meimeiDog.getName(),meimeiDog);
dogMap.put(feifeiDog.getName(),feifeiDog);
System.out.println("使用Inerator遍历,所有狗狗的昵称和品种分别是:");
Set keys = dogMap.keySet();
Iterator it = keys.iterator();
while(it.hasNext()) {
String key = (String)it.next();
Dog dog = (Dog)dogMap.get(key);
System.out.println(key + "\t" + dog.getStrain());
}
}
}