Collection类

普通的对象数组的最大问题在于数组中的元素个数是固定的,不能动态的扩充大小,所以最早的时候可以通过链表实现一个动态对象数组。但是这样做毕竟太复杂了,所以在 Java 中为了方便用户操作各个数据结构,所以引入了类集的概念,有时候就可以把类集称为 java 对数据结构的实现。
在整个类集中的,这个概念是从 JDK 1.2(Java 2)之后才正式引入的,最早也提供了很多的操作类,但是并没有完整的提出类集的完整概念。
类集中最大的几个操作接口:Collection、Map、Iterator,这三个接口为以后要使用的最重点的接口。
所有的类集操作的接口或类都在 java.util 包中。

Collection 接口

Collection 接口是在整个 Java 类集中保存单值的最大操作父接口,里面每次操作的时候都只能保存一个对象的数据。

定义:public interface Collection<E> extends Iterable<E>

方法:

开发中不会直接使用Collection接口。而是使用其子接口:List,Set。

List接口(重点)

在整个集合中List是Collection的子接口,里面的所有的内容都是允许重复的。

List子接口定义:

public interface List<E> extends Collection<E>

此接口上依然使用泛型,此接口还有如下扩充的方法:

List接口的实现类有ArrayList,Vector,LinkedList。

ArrayList(重点)

ArrayList 是 List 接口的子类,此类的定义如下:
public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, Serializable

此类继承了 AbstractList 类。AbstractList 是 List 接口的子类。AbstractList 是个抽象类,适配器设计模式。

方法使用:

ArrayList<String> all = new ArrayList<String>(); // 实例化 List 对象,并指定泛型类型
        all.add("hello "); // 增加内容,此方法从 Collection 接口继承而来
        all.add(0, "java ");// 增加内容,此方法是 List 接口单独定义的
        all.add("haha"); // 增加内容,此方法从 Collection 接口继承而来
        System.out.println(all); // 打印 all 对象调用 toString() 方法
//结果[java , hello , haha]
ArrayList<String> all = new ArrayList<String>(); // 实例化 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<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, Serializable

此类与 ArrayList 类一样,都是 AbstractList 的子类。所以,此时的操作只要是 List 接口的子类就都按照 List 进行操作。

List<String> all = new Vector<String>(); // 实例化 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基本没用什么区别。

Vector类和ArrayList类的区别(重点)

这两个类虽然都是 List 接口的子类,但是使用起来有如下的区别,如下。

LinkedList

此类的使用几率是非常低的,但是此类的定义如下:
public class LinkedList<E> extends AbstractSequentialList<E>implements List<E>, Deque<E>, Cloneable, Serializable

此类继承了 AbstractList,所以是 List 的子类。但是此类也是 Queue 接口的子类,Queue 接口定义了如下的方法:

Set接口(重点)

Set接口也是Collection的子接口,与List接口哦最大的不同在于,Set接口里面的内柔是不允许重复的。

此接口没用List接口中定义的get(int index)方法,所以无法使用循环进行输出。

此接口有两个子类:HashSet,TreeSet。

HashSet散列存放

既然 Set 接口并没有扩充任何的 Collection 接口中的内容,所以使用的方法全部都是 Collection 接口定义而来的。

HashSet 属于散列的存放类集,里面的内容是无序存放的。

演示:

Set<String> all = new HashSet<String>(); // 实例化 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<String> all = new HashSet<String>(); // 实例化 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 、 

但是,以上的操作不好,因为在操作的时候已经指定了操作的泛型类型,那么现在最好的做法是由泛型所指定的类型变为指定的数组。
所以只能使用以下的方法:<T> T[] toArray(T[] a)

Set<String> all = new HashSet<String>(); // 实例化 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 、 

排序的子类:TreeSet

与 HashSet 不同的是,TreeSet 本身属于排序的子类,此类的定义如下:
public class TreeSet<E> extends AbstractSet<E>implements NavigableSet<E>, Cloneable, Serializable

Set<String> all = new TreeSet<String>(); // 实例化 Set 接口对象 \
		all.add("D");
		all.add("X");
		all.add("A");
		System.out.println(all);
//结果[A, D, X]

虽然在增加元素的时候属于无序的操作,但是增加之后却可以为用户进行排序功能的实现。

排序的说明(重点)

既然 Set 接口的 TreeSet 类本身是允许排序,那么现在自定义一个类要进行排序就要实现 Comparable 接口。然后重写toString方法。重复的无法继续加入。

小结:
关于 TreeSet 的排序实现,如果是集合中对象是自定义的或者说其他系统定义的类没有实现Comparable 接口,则不能实现 TreeSet 的排序,会报类型转换(转向 Comparable 接口)错误。
换句话说要添加到 TreeSet 集合中的对象的类型必须实现了 Comparable 接口。不过 TreeSet 的集合因为借用了Comparable 接口,同时可以去除重复值,而 HashSet 虽然是
Set 接口子类,但是对于没有复写 Object 的 equals 和 hashCode 方法的对象,加入了 HashSet
集合中也是不能去掉重复值的。

集合输出(重点)

集合的输出也有多种形式· Iterator 迭代输出(90%)、ListIterator(5%)、Enumeration(1%)、foreach(4%)但是在讲解输出的时候一定要记住以下的原则:“只要是碰到了集合,则输出的时候想都不想就使用 Iterator 进行输出。

Iterator (绝对重点)

Iterator 属于迭代输出,基本的操作原理:是不断的判断是否有下一个元素,有的话,则直接输出。
此接口定义如下:
public interface Iterator<E>
要想使用此接口,则必须使用 Collection 接口,在 Collection 接口中规定了一个 iterator()方法,可以用于为 Iterator 接口进行实例化操作。
此接口规定了以下的三个方法:

通过 Collection 接口为其进行实例化之后,一定要记住,Iterator 中的操作指针是在第一条元素之上,当调用 next()方法的时候,获取当前指针指向的值并向下移动,使用 hasNext()可以检查序列中是否还有元素。

Collection<String> all = new ArrayList<String>();
all.add("A");
all.add("B");
all.add("C");
all.add("D");
all.add("E");
Iterator<String> 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 (理解)

ListIterator 是可以进行双向输出的迭代接口,此接口定义如下:
public interface ListIterator<E>extends Iterator<E>
此接口是 Iterator 的子接口,此接口中定义了以下的操作方法:

但是如果要想使用 ListIterator 接口,则必须依靠 List 接口进行实例化。

List 接口中定义了以下的方法:ListIterator<E> listIterator()

List<String> all = new ArrayList<String>();
all.add("A");
all.add("B");
all.add("C");
all.add("D");
all.add("E");
ListIterator<String> 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

Enumeration 是一个非常古老的输出接口,其也是一个元老级的输出接口,最早的动态数组使用 Vector 完成,那么只要是使用了 Vector 则就必须使用 Enumeration 进行输出。
此接口定义如下:
public interface Enumeration<E>

方法如下:

但是,与 Iterator 不同的是,如果要想使用 Enumeration 输出的话,则还必须使用 Vector 类完成,在类中定义了如下
方法:public Enumeration<E> elements()

Vector<String> v = new Vector<String>();
v.add("A");
v.add("B");
v.add("C");
Enumeration<String> enu = v.elements();
while (enu.hasMoreElements()) {
System.out.println(enu.nextElement());
}//结果ABC

foreach

foreach 可以用来输出数组的内容,那么也可以输出集合中的内容。

Collection<String> all = new ArrayList<String>();
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 输出的时候一定要注意的是,里面的操作泛型要指定具体的类型,这样在输出的时候才会更加有针对性

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值