09-Collection,泛型

@[TOC]

Collection集合

• 集合和数组都是一种容器。区别是:数组长度固定,但是集合可变。数组可以存储基本类型,或者对象;而集合只能存储对象。
• 集合框架
在这里插入图片描述

在这里插入图片描述

Collection常用功能

java.util.Collection接口:所有单列集合的最顶层的接口,里面定义了所有单列集合共性方法。任意单列集合都能使用Collection接口中的方法。

  • public boolean add(E e): 把给定的对象添加到当前集合中 。一般返回true,可以不接受
  • public void clear() :清空集合中所有的元素,不删除集合。
  • public boolean remove(E e): 把给定的对象在当前集合中删除。删除存在元素返回true;删除不存在,失败返回false。
  • public boolean contains(E e): 判断当前集合中是否包含给定的对象。
  • public boolean isEmpty(): 判断当前集合是否为空。
  • public int size(): 返回集合中元素的个数。
  • public Object[] toArray(): 把集合中的元素,存储到数组中。

使用:1.创建集合对象,可以使用多态
e.g.

1
2
3
4
5
6
// 使用多态,只需要改等号右边的集合类型,上面通用方法都可以使用
// Collection<String>coll= new ArrayList<>();
Collection<String>coll= new Hashset<>();
coll.add("mike");
coll.add("clara");
Object[] arr = coll.toArray();

Iterator迭代器

Java.util.Iterator接口:迭代器(对集合进行遍历)是Collection通用的取出集合元素的方式。
两个常用方法
boolean hasNext() 如果仍有元素可以迭代,则返回 true。
E next() 返回迭代的下一个元素。
Iterator是接口,我们无法直接使用,需要使用iterator接口的实现类对象,获取实现类方法比较特殊。
Collection接口有个方法,返回的就是迭代器的实现对象
Iterator<E> iterator() 返回在此 collection 的元素上进行迭代的迭代器。

使用步骤

  1. 使用集合中的方法iterator() 获得迭代器的实现对象,使用Iterator接口接收(多态)
  2. 使用Iterator接口中的方法 hasNext()判断有没有下一个元素
  3. 使用Iterator接口中的方法next() 取出集合中的下一个元素

注意:Iterator也是有泛型的,迭代器的泛型跟着接口走,集合是什么泛型,迭代器就是什么泛型。
E.g

1
2
3
4
5
6
7
8
9
10
Iterator<String> it = coll.iterator();
While(it.hasNext()) {
String s = it.next();
System.out.println(s);
}
System.out.println(---------------------);
for(Iterator<String> it2 = coll.iterator(); it2.hasNext(); ) {
String s = it.next();
System.out.println(s);
}

while循环通常用于不知道有多少元素,for循环一般用于知道有多少元素。

实现原理
获取迭代器的实现类对象,并且把指针(索引)指向集合的-1索引。
判断集合中有没有下一位元素,如果有就取出,然后把指针向后挪一位。

增强for(for each循环)
jdk1.5后出现,专门用来遍历数组和集合的。底层也是使用迭代器,只是用for循环格式简化书写,所以在遍历的过程中,不能对集合中的元素进行增删操作。

Collectionextends Iterable:所有的单列集合都可以使用增强for
public interface Iterable实现这个接口允许对象成为 “foreach” 语句的目标。

格式
for(集合/数组的数据类型 变量名:集合名/数组名) {
sout(变量名);
}

E.g

1
2
3
4
5
6
7
8
9
10
11
12
13
//遍历数组
int[] arr = {1,2,3,4,5};
for(int i : arr) {
system.out.println(i);
}
//遍历集合
ArrayList<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
for(String s : list) {
system.out.println(s);
}

泛型

概念

一种未知的数据类型,不知道使用什么类型时,可以使用泛型。也可以看作是一个变量,用来接收数据类型。

E,e:element 元素
T,t:type 类型
创建集合对象的时候,就会确定泛型的数据类型。

使用泛型好处
1.创建集合对象,不使用泛型
好处:默认使用Object类型,可以存储任意类型的数据
弊端:不安全,会引发异常
e.g

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ArrayList list = new AtrrayList ();
list.add("aa");
list.add(1);
Iterator it = list.iterator();
While(it.hasNext()) {
// 取出元素也是object类型
Object obj = it.next();
System.out.println(obj);

// 想要使用String特有的方法,比如length获取字符串长度,无法做到 多态 obj = “aa”
// 需要向下转型
String s = (String)obj;
System.out.println(s.length);
//但是由于第二个是Integer类型,不能把integer转换成string,会抛出异常ClassCastException
}

2.创建集合对象,使用泛型
好处:
1. 避免类型转换的麻烦,存储什么类型,取出就是什么类型
2. 把运行期代码异常提升到编译期(写代码时候就报错)

泛型的定义与使用

1.含有泛型的类
格式:

1
2
3
修饰符 class 类名<E> {

}

创建对象的时候确定泛型

2.含有泛型的方法
泛型定义在方法的修饰符和返回值类型之间
格式:

1
2
3
修饰符 <泛型> 返回类型 方法名 (参数列表<使用泛型>) {
方法体
}

调用方法时,确定泛型的类型(传递什么类型的参数,泛型就是什么类型)

3.含有泛型的接口
定义格式:

1
2
3
修饰符 interface 接口名<代表泛型的变量> { 

}

使用方式

  1. 定义类时确定泛型的类型
    e.g

    1
    2
    3
    public class MyImp1 implements MyGenericInterface<String> {
    // 实现接口…
    }
  2. 始终不确定泛型的类型,直到创建对象时,确定泛型的类型。
    e.g

    1
    2
    MyImp2<String>  my = new MyImp2<String>();
    my.add("aa");

泛型通配符

当使用泛型类或者接口时,传递数据中不能确定是什么泛型类型,可以使用<?>表示。
使用:不能创造对象使用;只能作为方法的参数使用
注意:

  1. 泛型没有继承概念
    Collection list = new ArrayList();这种是错误的。
  2. 一旦使用了通配符,只能使用object类中的共性方法,集合中元素自身方法无法使用。(比如可以用在遍历集合方法中)
  3. 上下限限定(看懂即可)
    泛型的上限限定: ?extends E 代表使用的泛型只能是E类型的子类/本身
    泛型的下限限定:?super E代表使用的泛型只能是E类型的父类/本身