普通的对象数组的最大问题在于数组中的元素个数是固定的,不能动态的扩充大小,所以最早的时候可以通过链表实现一个动态对象数组。但是这样做毕竟太复杂了,所以在 Java 中为了方便用户操作各个数据结构,所以引入了类集的概念,有时候就可以把类集称为 java 对数据结构的实现。
在整个类集中的,这个概念是从 JDK 1.2(Java 2)之后才正式引入的,最早也提供了很多的操作类,但是并没有完整的提出类集的完整概念。
类集中最大的几个操作接口:Collection、Map、Iterator,这三个接口为以后要使用的最重点的接口。
所有的类集操作的接口或类都在 java.util 包中。
Collection 接口是在整个 Java 类集中保存单值的最大操作父接口,里面每次操作的时候都只能保存一个对象的数据。
定义:public interface Collection
方法:
开发中不会直接使用Collection接口。而是使用其子接口:List,Set。
在整个集合中List是Collection的子接口,里面的所有的内容都是允许重复的。
List子接口定义:
public interface List
此接口上依然使用泛型,此接口还有如下扩充的方法:
List接口的实现类有ArrayList,Vector,LinkedList。
ArrayList 是 List 接口的子类,此类的定义如下:
public class ArrayList
此类继承了 AbstractList 类。AbstractList 是 List 接口的子类。AbstractList 是个抽象类,适配器设计模式。
方法使用:
ArrayList all = new ArrayList(); // 实例化 List 对象,并指定泛型类型
all.add("hello "); // 增加内容,此方法从 Collection 接口继承而来
all.add(0, "java ");// 增加内容,此方法是 List 接口单独定义的
all.add("haha"); // 增加内容,此方法从 Collection 接口继承而来
System.out.println(all); // 打印 all 对象调用 toString() 方法
//结果[java , hello , haha]
ArrayList all = new ArrayList(); // 实例化 List 对象,并指定泛型类型
all.add("hello "); // 增加内容,此方法从 Collection 接口继承而来
all.add(0, "java ");// 增加内容,此方法是 List 接口单独定义的
all.add("haha"); // 增加内容,此方法从 Collection 接口继承而来
all.remove(1); // 根据索引删除内容,此方法是 List 接口单独定义的
all.remove("haha");// 删除指定的对象
System.out.print(" 集合中的内容是: ");
for (int x = 0; x < all.size(); x++) { // size() 方法从 Collection 接口继承而来
System.out.print(all.get(x) + " 、 "); // 此方法是 List 接口单独定义的
}
// 集合中的内容是: java 、
clear()
移除此 collection 中的所有元素(可选操作)。
contains(Object o)
如果此 collection 包含指定的元素,则返回 true。
isEmpty()
如果此 collection 不包含元素,则返回 true。
size()
返回此 collection 中的元素数。
Vector(重点)
与 ArrayList 一样,Vector 本身也属于 List 接口的子类,此类的定义如下:
public class Vector
此类与 ArrayList 类一样,都是 AbstractList 的子类。所以,此时的操作只要是 List 接口的子类就都按照 List 进行操作。
List all = new Vector(); // 实例化 List 对象,并指定泛型类型
all.add("hello "); // 增加内容,此方法从 Collection 接口继承而来
all.add(0, "java ");// 增加内容,此方法是 List 接口单独定义的
all.add("world"); // 增加内容,此方法从 Collection 接口继承而来
all.remove(1); // 根据索引删除内容,此方法是 List 接口单独定义的
all.remove("world");// 删除指定的对象
System.out.print(" 集合中的内容是: ");
for (int x = 0; x < all.size(); x++) { // size() 方法从 Collection 接口继承而来
System.out.print(all.get(x) + " 、 "); // 此方法是 List 接口单独定义的
}
// 集合中的内容是: java 、
以上操作结果和ArrayList基本没用什么区别。
这两个类虽然都是 List 接口的子类,但是使用起来有如下的区别,如下。
此类的使用几率是非常低的,但是此类的定义如下:
public class LinkedList
此类继承了 AbstractList,所以是 List 的子类。但是此类也是 Queue 接口的子类,Queue 接口定义了如下的方法:
Set接口也是Collection的子接口,与List接口哦最大的不同在于,Set接口里面的内柔是不允许重复的。
此接口没用List接口中定义的get(int index)方法,所以无法使用循环进行输出。
此接口有两个子类:HashSet,TreeSet。
既然 Set 接口并没有扩充任何的 Collection 接口中的内容,所以使用的方法全部都是 Collection 接口定义而来的。
HashSet 属于散列的存放类集,里面的内容是无序存放的。
演示:
Set all = new HashSet(); // 实例化 Set 接口对象
all.add("A");
all.add("B");
all.add("C");
all.add("D");
all.add("E");
System.out.println(all);
//[A, B, C, D, E]
Set all = new HashSet(); // 实例化 Set 接口对象
all.add("A");
all.add("B");
all.add("C");
all.add("D");
all.add("E");
Object obj[] = all.toArray(); // 将集合变为对象数组
for (int x = 0; x < obj.length; x++) {
System.out.print(obj[x] + " 、 ");
}
//A 、 B 、 C 、 D 、 E 、
但是,以上的操作不好,因为在操作的时候已经指定了操作的泛型类型,那么现在最好的做法是由泛型所指定的类型变为指定的数组。
所以只能使用以下的方法:
Set all = new HashSet(); // 实例化 Set 接口对象
all.add("A");
all.add("B");
all.add("C");
all.add("D");
all.add("E");
String[] str = all.toArray(new String[] {});// 变为指定的泛型类型数组
for (int x = 0; x < str.length; x++) {
System.out.print(str[x] + " 、 ");
}
//A 、 B 、 C 、 D 、 E 、
与 HashSet 不同的是,TreeSet 本身属于排序的子类,此类的定义如下:
public class TreeSet
Set all = new TreeSet(); // 实例化 Set 接口对象 \
all.add("D");
all.add("X");
all.add("A");
System.out.println(all);
//结果[A, D, X]
虽然在增加元素的时候属于无序的操作,但是增加之后却可以为用户进行排序功能的实现。
既然 Set 接口的 TreeSet 类本身是允许排序,那么现在自定义一个类要进行排序就要实现 Comparable 接口。然后重写toString方法。重复的无法继续加入。
集合的输出也有多种形式· Iterator 迭代输出(90%)、ListIterator(5%)、Enumeration(1%)、foreach(4%)但是在讲解输出的时候一定要记住以下的原则:“只要是碰到了集合,则输出的时候想都不想就使用 Iterator 进行输出。
Iterator 属于迭代输出,基本的操作原理:是不断的判断是否有下一个元素,有的话,则直接输出。
此接口定义如下:
public interface Iterator
要想使用此接口,则必须使用 Collection 接口,在 Collection 接口中规定了一个 iterator()方法,可以用于为 Iterator 接口进行实例化操作。
此接口规定了以下的三个方法:
通过 Collection 接口为其进行实例化之后,一定要记住,Iterator 中的操作指针是在第一条元素之上,当调用 next()方法的时候,获取当前指针指向的值并向下移动,使用 hasNext()可以检查序列中是否还有元素。
Collection all = new ArrayList();
all.add("A");
all.add("B");
all.add("C");
all.add("D");
all.add("E");
Iterator iter = all.iterator();
while (iter.hasNext()) {// 判断是否有下一个元素
String str = iter.next(); // 取出当前元素
System.out.print(str + " 、 ");
//结果A 、 B 、 C 、 D 、 E 、
以上的操作是 Iterator 接口使用最多的形式,也是一个标准的输出形式。
但是在使用 Iterator 输出的时候有一点必须注意,在进行迭代输出的时候如果要想删除当前元素,则只能使用 Iterator接口中的 remove()方法,而不能使用集合中的 remove()方法。否则将出现未知的错误。
Iterator 接口本身可以完成输出的功能,但是此接口只能进行由前向后的单向输出。如果要想进行双向输出,则必须使用其子接口 —— ListIterator。
ListIterator 是可以进行双向输出的迭代接口,此接口定义如下:
public interface ListIterator
此接口是 Iterator 的子接口,此接口中定义了以下的操作方法:
但是如果要想使用 ListIterator 接口,则必须依靠 List 接口进行实例化。
List 接口中定义了以下的方法:ListIterator
List all = new ArrayList();
all.add("A");
all.add("B");
all.add("C");
all.add("D");
all.add("E");
ListIterator iter = all.listIterator();
System.out.print(" 从前向后输出: ");
while (iter.hasNext()) {
System.out.print(iter.next() + " 、 ");
}
System.out.print("\n 从后向前输出: ");
while (iter.hasPrevious()) {
System.out.print(iter.previous() + " 、 ");
}
//结果 从前向后输出: A 、 B 、 C 、 D 、 E 、
//从后向前输出: E 、 D 、 C 、 B 、 A 、
Enumeration 是一个非常古老的输出接口,其也是一个元老级的输出接口,最早的动态数组使用 Vector 完成,那么只要是使用了 Vector 则就必须使用 Enumeration 进行输出。
此接口定义如下:
public interface Enumeration
方法如下:
但是,与 Iterator 不同的是,如果要想使用 Enumeration 输出的话,则还必须使用 Vector 类完成,在类中定义了如下
方法:public Enumeration
Vector v = new Vector();
v.add("A");
v.add("B");
v.add("C");
Enumeration enu = v.elements();
while (enu.hasMoreElements()) {
System.out.println(enu.nextElement());
}//结果ABC
foreach 可以用来输出数组的内容,那么也可以输出集合中的内容。
Collection all = new ArrayList();
all.add("A");
all.add("B");
all.add("C");
all.add("D");
all.add("E");
for (String str : all) {
System.out.println(str) ;
}
//ABCDE
在使用 foreach 输出的时候一定要注意的是,里面的操作泛型要指定具体的类型,这样在输出的时候才会更加有针对性