Java的类集框架可以使程序处理对象的方法标准化,类集接口是构造类集框架的基础,使用迭代方法访问类集可以使对类集的操作更高效。
一、认识类集框架
在基础应用中,通常我们可以通过数组来保存一组具有相同属性的对象或者基本类型的数据,但使用数组的弊端在于其大小是不可更改的,因此出于灵活性的考虑,可以使用链表来实现动态的数组。任何事情都有两面性,灵活性的代价就是操作上的繁琐。
在计算机世界里,处理繁琐问题的常用方法就是将其封装,只向外提供可调用的方法视图。
Java类集框架就是对这一方法的一种官方实现—套动态对象数组的操作类。本质上,Java类集框架就是Java对数据结构的一个大体上的封装。
类集是在JDK 1.2之后正式提出的概念。从类集开始用户就没有必要再像之前自己来编写链表了。但是类集的内部实现原理依然和之前一样,就是一个动态的对象数组,所不同的是,这个动态数组处理的细节,已被包装屏蔽起来了。这个理念和C++中STL (Standard Template Library,标准模板库)是一脉相承的。
在java.util包之中定义了所有与类集有关的操作接口:Collection、List、Set、Map、Iterator、ListIterator及Enumeration。
在JDK1.5之后,这些接口都增加了泛型的定义,最早的时候这些接口中的内容都使用Object(对象)进行操作。出于安全性的考虑,以及避免转型之间的繁琐,JDK1.5以后将整个类集框架都升级为泛型(Generic programming),极大方便了用户。
在Java中,每个变量都有其所属的数据类型,要么是基本的数据类型(int,float,char等),要么是自定义的数据类型—即类,而泛型的本质就是将变量的“类型”参数化,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别被称为泛型类、泛型接口、泛型方法。
二、类集接口
类集框架定义了几个接口。类集接口决定了Collection类的基本特性。具体类仅仅是提供了标准接口的不同实现。
支持类集的接口总结在下表中:
(1)在这些接口中定义了操作该类集的一些方法。
(2)支持这些方法的类集被称为可修改的(modifiable)。
(3)不允许修改其内容的类集被称为不可修改的(unmodifiable)。
(4)所有内置的类集都是可修改的。
(5)如果对一个不可修改的类集使用这些方法,将引发一个UnsupportedOperationException异常。
三、Collection——单值保存的最大父类接口
Collection接口是构造类集框架的基础,是单值数据操作的最大父接口,它声明了所有类集都将拥有的核心方法。如下:
由于所有类集均实现了Collection,所以熟悉它的方法对于清楚地理解框架是必要的。
(1)如果对一个不可修改的类集使用这些方法,将引发一个UnsupportedOperationException异常。
(2)当一个对象与另一个对象不兼容,例如企图增加一个不兼容的对象到一个类集中时,将产生一个ClassCastException异常。
在Collection接口之中所提供的方法一定是在日后进行程序开发中使用最多的方法,但是Collection接口很少在开发之中直接去使用,往往都会使用它的子接口:
(1)List(允许有重复元素)
(2)Set(不允许有重复元素)。
四、Collection接口的具体实现类
五、允许重复的子接口——List
List(列表)是Collection接口之中最为常用的一个子接口,首先来观察一下List子接口的定义。
public interface List<E> extends Collection<E>
List子接口对Collection接口进行了大量的扩充。 List接口扩展了Collection并声明存储一系列元素的类集的特性。使用一个基于零的下标,元素可以通过它们在列表中的位置被插入和访问。
一个列表可以包含重复的元素,即可以存在完全相同的两个元素。
除了由Collection定义的方法之外,List还定义了一些它自己的方法,如下:
需要注意的是,当类集不能被修改时,其中的几种方法将引发UnsupportedOperationException异常。当一个对象与另一个不兼容时,例如企图将一个不兼容的对象加入一个类集中,将产生ClassCastException异常。
由于List本身毕竟还属于接口,要想使用接口,就必须知道实现这个接口的子类,在List接口中有两个最为常用的子类:ArrayList、Vector。
1、ArrayList类
ArrayList类扩展AbstractList并执行List接口。ArrayList支持可随需要而增长的动态数组。
在Java中,标准类型的数组是定长的。一旦数组被创建之后,它们不能被加长或缩短,这也就意味着开发者必须事先知道数组可以容纳多少元素。但是在一般情况下,只有在运行时才能知道需要多大的数组。为了解决这个问题,类集框架定义了ArrayList。
本质上,ArrayList是对象引用的一个变长数组。 也就是说,ArrayList能够动态地增加或减小其大小。
数组列表以一个原始大小被创建。当超过了它的大小时,类集就会自动增大。当有对象被删除,数组就可以缩小。
注意:动态数组也被从以前版本遗留下来的类Vector所支持。
ArrayList有如下的构造方法:
(1)ArrayList( ) : 构造一个初始容量为 10 的空列表
(2)ArrayList(Collection c) : 建立一个数组列表,该数组列表由类c中的元素初始化
(3)ArrayList(int capacity) :建立一个数组列表,该数组有指定的初始容量(capacity),容量是用于存储元素的基本数组的大小。当元素被追加到数组列表上时,容量会自动增加。
package com.xy.collection;
import java.util.ArrayList;
public class ArrayListDemo1 {
public static void main(String[] args) {
ArrayList<String> a1 = new ArrayList<String>();
System.out.println("a1中初始元素的个数:" + a1.size());
// 向ArrayList对象中添加新的内容
a1.add("Hello");
a1.add("world");
a1.add("Hello");
a1.add("Java");
System.out.println(a1);
a1.add(1, "Java");
System.out.println(a1);
}
}
【结果】
2、LinkedList类
LinkedList类扩展了AbstractSequentialList类并实现List接口。它提供了一个链接列表的数据结构。
它具有如下的两个构造方法:
(1)LinkedList( ) : 建立一个空的链接列表。
(2)LinkedList(Collection c) : 建立一个链接列表,该链接列表由类c中的元素初始化。
除了它继承的方法之外,LinkedList类本身还定义了一些有用的方法,这些方法主要用于操作和访问列表。
方法 | 作用 |
---|---|
void addFirst(Object obj) | 在列表头增加元素 |
void addLast(Object obj) | 在列表的尾部增加元素 |
Object getFirst( ); | 获得第1个元素 |
Object getLast( ); | 得到最后一个元素 |
Object removeFirst( ); | 删除第1个元素 |
Object removeLast( ); | 删除最后一个元素 |
package com.xy.collection;
import java.util.LinkedList;
public class LinkedListDemo1 {
public static void main(String[] args) {
LinkedList<String> ll = new LinkedList<String>();
ll.add("Hello");
ll.add("Java");
ll.add("!!!");
ll.<