类集的概念是从JDK 1.2 之后正式完善的一套开发架构,其基本的作用就是完成了一个动态的对象数组,里面的数据元素可以动态的增加
类集提供了以下的几种接口:
单值操作接口:Collection、List、Set
List 和 Set 是Collection 接口的子接口
一对值的操作接口:Map
排序的操作接口:SortedMap、SortedSet
输出的接口:Iterator、ListIterator、Enumetation
队列:Queue
所有的类集都保存在java.util包中,此包是一个最重要的工具包
Collection 接口
Collection 接口是一个最重要的操作接口,其中规定了一个集合的基本操作方法,此接口下有两个子接口,这两个子接口又分别有首各自的特点,在使用上完全不一样
Collection 接口定义:
public interface Collection
extends Iterable
在JDK1.5之后,Collection接口使用了泛型技术,那么这样做的目的可以保证接口中的操作的内容更加安全,因为最早来讲为了保证 Collection接口中可以增加任意的对象内容,所以使用了Object 进行接收,但是因为其可以接收任意的内容,所以在使用中就有可能在一个集合中插入不同的对象,在取出的时候就有可能出现类转换异常,所以在实际的类集操作中一定要指明其具体的操作泛型类型。
Coolection 接口中定义了如下的方法
No. | 方法 | 类型 | 描述 |
1 | public boolean add(E a) | 普通 | 向集合中增加元素 |
2 | public bollean addAll(Collection extends E>c) | 普通 | 向集合中加入一组数据,泛型指定了操作上限 |
3 | public void clear() | 普通 | 清空所有的内容 |
4 | public boolean contains(Object 0) | 普通 | 判断是否有指定的内容,查找 |
5 | public boolean containsAll(Collection>c) | 普通 | 查找一组数据是否存在 |
6 | public boolean equals(Object o) | 普通 | 对象比较 |
7 | public in hashCode() | 普通 | 返回hash 码 |
8 | public bollean is Empty() | 普通 | 判断集合的内容是否为空 |
9 | public Iterator |
普通 | 为iterator 实例化,迭代输出 |
10 | public boolean remove(Object o) | 普通 | 从集合中删除指定的对象 |
11 | public boolean removeAll(Collection> c) | 普通 | 从集合中删除一组对象 |
12 | public boolean retainAll(Collection> c) | 普通 | 从集合中保留指定的对象 |
13 | public int size() | 普通 | 取得集合的长度 |
14 | public Object[] toArray() | 普通 | 取得全部的内容,以数据集合的形式返回 |
15 | public |
普通 | 取得全部的内容 |
从现化的开发中来看,在集合操作中已经很少去使用Collection 完成功能了,基本上都使用了其子接口:List、Set
List 接口
List 接口最大的特点是里面的内容都允许重复。但是,此接口比Collection 接口扩充了很多的方法
以下的方法是新增加的操作:
No. | 方法 | 类型 | 描述 |
1 | public void add(int index,E element) | 普通 | 在指定的位置入加入元素 |
2 | public bollean add All(int index x,Collection extends E> c) | 普通 | 在指定位置增加一组元素 |
3 | public E get(int index) | 普通 | 通下索引位置可以取出每一个元素 |
4 | public ListIterator |
普通 | 为ListIterator 接口实例化 |
5 | public E remove(int index) | 普通 | 删除指定位置内容 |
6 | public E set(int index ,E element) | 普通 | 修改指定位置内容 |
7 | public List |
普通 | 截取子集合 |
如果要想使用List 接口,则要通过其子类,常用的子类有如下几个:ArrayList、Vector、LinkedList
新的子类:ArrayList
ArrayList 是List 接口最常用的一个子类其定义如下:
public class ArrayList
extends AbstractList
implements List,RandomAccess,Cloneable,Serializable
使用ArrayList 的对象可以直接为List 接口实例化
完成增加数据的操作
package org.collectiondemo.listdemo;
import java.util.ArrayList;
import java.util.List;
public class ArrayListAddDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
List alllist = new ArrayList(); //为List 接口实例化
alllist.add("Hello"); //增加元素,Collection接口定义
alllist.add("MSDL"); //增加元素,Collection接口定义
alllist.add(0,"World"); //增加元素,List接口定义
alllist.add(0,"Temp"); //增加元素,List接口定义
System.out.println(alllist);
}
}
通过代码运行可以发现此程序是没有数组长度限制的
完成删除数据的操作
package org.collectiondemo.listdemo;
import java.util.ArrayList;
import java.util.List;
public class ArrayListDeleteDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
List alllist = new ArrayList();
alllist.add("Hello"); //增加元素,Collection接口定义
alllist.add("MSDL"); //增加元素,Collection接口定义
alllist.add(0,"World"); //增加元素,List接口定义
alllist.add(0,"Temp"); //增加元素,List接口定义
alllist.remove("World"); //删除第一个位置的元素,List接口宝义
alllist.remove(0);//删除第一个位置的元素,List 接口定义
System.out.println(alllist);
}
}
完成输出数据的操作
在List 接口中提供了一个get(int index) 方法,此方法可以根据索引位置取出数据
package org.collectiondemo.listdemo;
import java.util.ArrayList;
import java.util.List;
public class ArrayListPrintDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
List alllist = new ArrayList();
alllist.add("Hello"); //增加元素,Collection接口定义
alllist.add("MSDL"); //增加元素,Collection接口定义
alllist.add(0,"World"); //增加元素,List接口定义
alllist.add(0,"Temp"); //增加元素,List接口定义
for (int i=0;i
在Collection 接口中实际 上也规定了两个可以将集合变为对象数组的操作
package org.collectiondemo.listdemo;
import java.util.ArrayList;
import java.util.Collection;
public class ArrayListPrintDemo01 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Collection alllist = new ArrayList();
alllist.add("Hello"); //增加元素,Collection接口定义
alllist.add("MSDL"); //增加元素,Collection接口定义
Object obj[] = alllist.toArray();
for (int i=0;i
package org.collectiondemo.listdemo;
import java.util.ArrayList;
import java.util.Collection;
public class ArrayListPrintDemo02 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Collection alllist = new ArrayList();
alllist.add("Hello"); //增加元素,Collection接口定义
alllist.add("MSDL"); //增加元素,Collection接口定义
String obj[] = alllist.toArray(new String[]{});
for (int i=0;i
集合的其他操作方法
判断元素是否存在
List 接口中定义的subList()方法
package org.collectiondemo.listdemo;
import java.util.ArrayList;
import java.util.List;
public class ArrayListOtherDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
List alllist = new ArrayList(); //为List 接口实例化
alllist.add("Hello"); //增加元素,Collection接口定义
alllist.add("MSDL"); //增加元素,Collection接口定义
alllist.add(0,"World"); //增加元素,List接口定义
alllist.add(0,"Temp"); //增加元素,List接口定义
System.out.println(alllist.contains("World"));
System.out.println(alllist.subList(2, 3));
}
}
旧的子类:Vector
Vector 类是一个元老级的操作类,在JDK1.0推出的时候就有了,ArrayList 类是在JDK1.2之后才定义的新操作类,但是因为考虑到一部份人已经习惯于使用Vector类,所以,Java的开发者在定义类集的时候又让Vector类多实现了一个List接口,所以此类可以直接为List接口实例化
package org.collectiondemo.listdemo;
import java.util.List;
import java.util.Vector;
public class VectorAddDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
List alllist = new Vector(); //为List 接口实例化
alllist.add("Hello"); //增加元素,Collection接口定义
alllist.add("MSDL"); //增加元素,Collection接口定义
alllist.add(0,"World"); //增加元素,List接口定义
alllist.add(0,"Temp"); //增加元素,List接口定义
System.out.println(alllist);
}
}
当然,需要说明的是,在Vector类因为是一个比较老的类,所以里面也定义了自己的增加数据的操作,例如:public void addElement(E obj),那么现在此就去的操作跟List中是完全一样的。
ArrayList 与 Vector 的区别
ArrayList 类和Vector类都是List 接口的子类
No | 区别点 | ArrayList | Vector |
1 | 推出时间 | 是在JDK1.2之后推出的,属于新的类 | 是在JDK1.0时推出的,属于旧的操作类 |
2 | 操作 | ArrayList 采用异步的处理操作 | Vecotr采用同步的处理操作 |
3 | 性能 | ArrayList 性能高 | Vector 性能相对较低 |
4 | 安全 | 非线程安全的操作 | 线程安全 |
5 | 输出 | Iterator、ListIterator、foreach | Iterator、ListIterator、foreach、Enumeration |
LinkedList 和 Queue 接口
LinedList 完成的是一个链表的操作,可以方便的找到表头之类的基本操作。
此类定义如下:
public class LinkedList
extends AbstractSequentialList
implements List,Deque,Cloneable,Serializable
此类提供的方法就是链表操作方法
package org.collectiondemo.listdemo;
import java.util.LinkedList;
public class LinkedDemo01 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
LinkedList link = new LinkedList();
link.add("A");
link.add("B");
link.add("C");
link.addFirst("X");
link.addLast("Y");
System.out.println(link);
for (int i = 0;i
取出表头的操作
package org.collectiondemo.listdemo;
import java.util.LinkedList;
public class LinkedListDemo02 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
LinkedList link = new LinkedList();
link.add("A");
link.add("B");
link.add("C");
link.addFirst("X");
link.addLast("Y");
System.out.println(link);
for (int i = 0;i
Set 接口
Set 接口也是Collection的子接口,最大的特点是里面没有任何的重复元素,在Set 接口中有以下的两个子类是最常用的子类
TreeSet :有序存放
HashSet: 散列存放
Set 接口本身并没有对Collection接口做任何的扩充,是安全一样
HashSet 散列存放
package org.collectiondemo.listdemo;
import java.util.HashSet;
import java.util.Set;
public class HashSetAddDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Set allSet = new HashSet();
allSet.add("A"); //增加重复元素
allSet.add("A"); //增加重复元素
allSet.add("B"); //增加
allSet.add("C"); //增加
allSet.add("D"); //增加重复元素
allSet.add("D"); //增加重复元素
System.out.println(allSet);
}
}
TreeSet 有序存放
TreeSet 是可以进行排序的操作接口
package org.collectiondemo.listdemo;
import java.util.TreeSet;
import java.util.Set;
public class HashSetAddDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Set allSet = new TreeSet();
allSet.add("A"); //增加重复元素
allSet.add("A"); //增加重复元素
allSet.add("B"); //增加
allSet.add("C"); //增加
allSet.add("D"); //增加重复元素
allSet.add("D"); //增加重复元素
System.out.println(allSet);
}
}
关于排序的说明
在之前的操作中使用的是String类的对象向集合中加入,如果现在自定义了一个类
package org.collectiondemo.listdemo;
public class Person implements Comparable {
private String name;
private int age;
public Person(String name,int age){
this.name = name;
this.age = age;
}
public String toString(){
return "姓名:"+this.name+" 年龄:"+this.age;
}
public boolean equals(Object obj){
if (this == obj){
return true;
}
if (!(obj instanceof Person)){
return false;
}
Person per = (Person)obj;
if (this.name.equals(per.name) && this.age == per.age){
return true;
}else{
return false;
}
}
public int hashCode(){ //这个方法的返回值都是通过一个公式计算的
// 此时的公式:名字的hashCode * age
return this.name.hashCode() * this.age;
}
@Override
public int compareTo(Person per) {
// TODO Auto-generated method stub
if (this.age < per.age){
return -1;
}else if (this.age > per.age){
return 1;
}else{
return this.name.compareTo(per.name); //比较name
}
}
}
package org.collectiondemo.listdemo;
import java.util.Set;
import java.util.TreeSet;
public class TreeSetPersonDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Set setp = new TreeSet();
setp.add(new Person("张三",20));
setp.add(new Person("李四",20));
setp.add(new Person("王五",20));
setp.add(new Person("赵六",20));
setp.add(new Person("孙七",20));
setp.add(new Person("孙七",20));
System.out.println(setp);
}
}
关于重复元素的说明
如果将以上的程序替换成HashSet子类,则会发现存在了重复元素,那么现在覆写equals()方法。
而且如果要想完成对象重复元素的判断,还需要覆写Object类中的hashCode()方法
在程序中是通过Object 类中的hashCode()和euqals()方法来完成重复元素的验证
所以,一个完整的类必须覆写Object 类中的hashCode()和equals()方法就在这里。
集合输出
在Java 的类集中集合输出有以下四种方式:
Iterator
ListIterator
foreach
Enumeration
但是在讲解之前先给一个标准的开发模式:“只要是碰到集合的输出,使用Iterator 接口”
Iterator
Iterator 表示迭代接口。Iterator 接口中定义了如下的方法
No | 方法 | 类型 | 描述 |
1 | public boolean hasNext() | 普通 | 将指针向下移动,判断是否还有内容 |
2 | public E next() | 普通 | 取出当前指针位置的内容 |
3 | public void remove() | 普通 | 删除当前指针位置的内容 |
如果要想为Iterator 接口实例化,则必须使用Collection接口的如下方法:
public Iterator iterator()
通过以下代码观察Iterator 的使用
package org.iteratordemo;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class ListIteratorDemo01 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
List allList = new ArrayList();
allList.add("A");
allList.add("A");
allList.add("B");
allList.add("C");
allList.add("D");
ListIterator listiter = allList.listIterator();
while (listiter.hasNext()){
System.out.println(listiter.next());
}
System.out.println(allList);
}
}
但是在Iterator 接口中存在一个删除的方法,在使用此方法的时候一定要有注意
正确的删除:
package org.iteratordemo;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class ListIteratorDemo03 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
List allList = new ArrayList();
allList.add("A");
allList.add("A");
allList.add("B");
allList.add("C");
allList.add("D");
ListIterator listiter = allList.listIterator();
listiter.add("E");
while (listiter.hasNext()){
String str = listiter.next(); //取出内容
if ("D".equals(str)){
listiter.remove(); //删除元素,使用的是List 接口的删除
}
System.out.print(str+"、");
}
System.out.println("");
while (listiter.hasPrevious()){
System.out.print(listiter.previous()+"、");
}
}
}
不正确的删除操作:
package org.iteratordemo;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class ListIteratorDemo03 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
List allList = new ArrayList();
allList.add("A");
allList.add("A");
allList.add("B");
allList.add("C");
allList.add("D");
ListIterator listiter = allList.listIterator();
listiter.add("E");
while (listiter.hasNext()){
String str = listiter.next();
if ("D".equals(str)){
allList.remove(str);
}
System.out.print(str+"、");
}
System.out.println("");
while (listiter.hasPrevious()){
System.out.print(listiter.previous()+"、");
}
}
}
因为所谓的Iterator 实际上,只是将一个集合的内容交给了Iterator 输出而已,而如果直接使用了集合中的remove()方法,删除的话,则会存坏整个集合的内容,所以输出的时候会出现问题。
而在实际的开发中是很少使用Iterator 进行删除的操作,只是判断是否有值并且将值输出
ListIterator
ListIterator 是Iterator 接口的子接口。Iterator接口的最大特点,是能从前向后迭代输出,如果现在要想执行双向的输出,则只能使用ListIterator 接口,但是此接口使用时有一个要求,即:只能输出List接口的内容,因为要依靠如下的方法
public ListIterator listIterator()
此接口的操作方法如下:
No. | 方法 | 类型 | 描述 |
1 | public void add(E e) | 普通 | 增加数据 |
2 | public boolean hasNext() | 普通 | 从Iterator 继承而来 |
3 | public E next() | 普通 | 从Iterator 继承而来 |
4 | public void remove() | 普通 | 从Iterator 继承而来 |
5 | public bollean hasPrevious() | 普通 | 判断是否有前一个元素 |
6 | public E previous() | 普通 | 取出前一个元素 |
7 | public void set(E e) | 普通 | 修改元素内容 |
下面就使用ListIterator 接口进行双向的输出操作
package org.iteratordemo;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class ListIteratorDemo02 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
List allList = new ArrayList();
allList.add("A");
allList.add("A");
allList.add("B");
allList.add("C");
allList.add("D");
ListIterator listiter = allList.listIterator();
System.out.print("从前向后输出:");
while (listiter.hasNext()){System.out.print(listiter.next()+"、");}System.out.println("\n从后向后输出:");while (listiter.hasPrevious()){System.out.print(listiter.previous()+"、");}System.out.println(allList);}}
在使用Listerator 接口的时候还有一个特别大的特点,可以增加及修改数据
package org.iteratordemo;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class ListIteratorDemo03 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
List allList = new ArrayList();
allList.add("A");
allList.add("A");
allList.add("B");
allList.add("C");
allList.add("D");
ListIterator listiter = allList.listIterator();
listiter.add("E"); //增加数据
while (listiter.hasNext()){
String str = listiter.next();
listiter.set(str + "-- MSDL"); //修改数据
System.out.print(str+"、");
}
System.out.println("");
while (listiter.hasPrevious()){
System.out.print(listiter.previous()+"、");
}
}
}
foreach
在数组的输出上可以使用foreach 完成,那么对于集合也同样适用
package org.iteratordemo;
import java.util.ArrayList;
import java.util.List;
public class ForeachDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
List allList = new ArrayList();
allList.add("A");
allList.add("A");
allList.add("B");
allList.add("C");
allList.add("D");
for (String str : allList){
System.out.println(str);
}
}
}
废弃的接口:Enumeration
Enumeration 是一个古老的输出接口,支持此种输出的类只有Vector类
在Vector类中存在以下的方法:public Enumeration
Enumeration 接口定义了如下的方法:
判断是否还有内容:boolean hasMoreElements()
取出内容:E nextElement()
可以发现此接口定义的方法功能与Iterator类似,而且单词比 Iterator 长很多,所以记得费劲,所以基本上不使用
package org.iteratordemo;
import java.util.Enumeration;
import java.util.Vector;
public class EnumerationDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Vector allList = new Vector();
allList.add("A");
allList.add("A");
allList.add("B");
allList.add("C");
allList.add("D");
Enumeration enu = allList.elements();
while(enu.hasMoreElements()){
System.out.println(enu.nextElement());
}
}
}
当然,对于一些旧的操作类中现在依然支持Eumeration ,这一点在日后的Java Web 的开发中可以见到。所以掌握此接口也是很有必要的。