- Collection集合
- 迭代器
- 增强型for循环
- 泛型
目标:
- 区分集合和数组的区别
- 使用Collection集合的常用功能
- 使用迭代器
- 掌握集合使用细节
- 使用集合存储自定义类型
- 使用for each循环遍历集合
- 使用泛型定义集合对象
- 理解泛型上下限
- 阐述泛型通配符作用
Collection集合
概述: 前面我们已经接触过ArrayList集合,那么集合到底是什么呢?
集合是Java中提供的一种容器,可以来存储多个数据。集合和数组既然都是容器,他们有何区别?
- 数组的长度是固定的,集合的长度是可变的
- 数组中存储的是同一种数据类型的元素,可以存储基本数据类型,也可以存储引用数据类型。集合存储的都是引用数据类型,对象的数据类型可以不一致。在开发当中一般当对象多的时候,使用集合存储数据。
集合的框架
JavaSE提供了满足各自需求的API,我们在使用API的时候,先了解其继承与接口操作的框架,然后才能理解使用哪个类更灵活的适合设计你的程序。
根据集合的存储结构,分为了两个大类:
- 单列集合 ---
java.util.Collection
- 双列集合 ---
java.util.Map
Vector | |||
---|---|---|---|
List接口(有序) | ArrayList | ||
LinkedList | |||
Collection接口 | |||
TreeSet(无序) | |||
Set接口 | HashSet(无序) | LinkedHashSet(有序) |
List接口:
- 有序的集合(存储和取出元素顺序相同)
- 允许存储重复元素
- 有索引,可以进行普通for遍历
Set接口:
- 不允许存储重复性元素
- 没有索引(不能使用普通for遍历)
Collection接口:
-
定义的是所有单列集合中共性的API方法,所有单列集合都可以使用共性的方法
-
没有带索引的方法
它是单列集合的根接口,用于存储一系列符合某种规则的元素,又两个重要的子接口
java.util.List
和java.util.Set
Collection集合常用功能
- public boolean add(E e):把给定的对象添加到当前的集合当中
- public void clear():清空集合当中所有元素
- public boolean remove(E e):把给定的对象从当前集合中删除掉
- public boolean contains(E e):判断当前集合当中是否包含给定的对象
- public boolean isEmpty():判断当前集合是否为空
- public int size():获取当前集合元素的个数
- public Object[ ] toArray():把当前集合中的元素,存储到一个数组中
迭代器Iterator接口
在程序开发过程中,经常需要遍历集合中所有元素,针对此情况,JDK官方提供了一个java.util.Iterator
,这个接口也是集合当中的一员,但是它与Map、Collection接口不同。Map、Collection集合主要是来存储元素的,而Iterator主要用于迭代访问Collection与Map集合中的元素。因此,经常把Iterator对象称为迭代器
遍历Collection集合当中的元素,首先应获取该集合的迭代器,通过迭代器完成迭代
-
public Iterator iterator():获取集合对应的迭代器
迭代的具体实现:在每次取元素之前首先判断有没有元素,如果有,就把这个元素取出,继续再判断,如果还有就再取一次出来。直至集合为空。
Iterator接口的常用方法:
- public E next():获取迭代的下一个元素
- public boolean hasNext():如果集合当中仍有元素可以迭代,则返回true,如果没有元素则返回false
在调用Iterator接口当中的next方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next方法后,迭代器的索引向后移动一位,指向第一个元素并将该元素返回。当再次调用next方法时,迭代器的索引会指向第二个元素并将该元素返回。依次类推,直至hasNext方法返回false。表示迭代器达到集合的末尾,终止对元素遍历,如果再取,则抛出java.util.NoSuchElementException
备注:Iterator
增强for循环
在JDK1.5之后出现了一个新的循环结构,for each循环,(增强型for循环)。专门遍历数组和集合 它的内部原理其实是由迭代器实现,在迭代过程中,不能对集合当中的元素进行增删操作。
格式:
for(元素的数据类型 变量名 :Collection集合或者数组){
//操作代码
//...
}
主要用于遍历Collection集合或者数组,在遍历的过程中,一定不要进行增删操作。
示例:
for (int i:arr) {//遍历数组
System.out.println(i);
}
for (String e: coll) {//遍历集合
System.out.println(e);//e表示集合中的元素
}
备注:目标只能是Collection集合或者数组,增强for循环仅仅是作为遍历操作出现。简化迭代器的操作
泛型
是一种未知的数据类型,当我们不知道要使用什么样的数据类型的时候,可以使用泛型。我们也可以将泛型看做是一个变量,用来接收数据类型(预支的使用未知的数据类型)
- E e :Element 元素
- T t :Type 类型
定义集合的时候 不知道要使用什么样的数据类型的时候,使用泛型
public class ArrayList<E>{
public boolean add(E e){}
public E get(int index){}
}
创建集合对象的时候,一定要确定具体泛型类型 当没有指定具体数据类型时,默认指定为Object类型
ArrayList<String> list =new ArrayList();
public class ArrayList<String>{
public boolean add(String){}
public String get(int index){}
}
使用泛型的好处:
- 避免类型转换之间的麻烦,存储的是什么数据类型,取出的就是什么样的数据类型
- 运行期异常提前到了编译期
备注:泛型其实也是数据类型的一部分,一般我们将类名和泛型合并一起看做数据类型
泛型的定义与使用
泛型可以灵活的将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数进行传递
因为我们的集合框架体系中,大量的使用了泛型。
定义和含有泛型的类
修饰符 class 类名<代表泛型的变量>{
}
例如:
public class GenericDemo02<W> {
private W name;
public GenericDemo02() {
}
public GenericDemo02(W name) {
this.name = name;
}
public W getName() {
return name;
}
public void setName(W name) {
this.name = name;
}
}//定义的时候使用未知泛型变量,使用的时候确定具体类型(创建对象的时候)
定义和含有泛型的方法
修饰符 <代表泛型的变量> 返回值类型 方法名(泛型参数列表){
}
例如:
public class GenericMethod{
//定义带有泛型的方法
public <VIP> void show(VIP vip){
System.out.println(vip);
}
//定义一个含有泛型返回值的方法
public <VIP> VIP show(VIP vip){
//...
return vip;
}
}
main(){
new GenericMethod().show("abc");// 自动转换为String类型 vip = "abc"
new GenericMethod().show(123);// 自动转换为int类型 vip = 3.14
}
定义和含有泛型的接口
修饰符 interface 接口名<代表泛型的变量>{
}
例如:
public interface Collection<E>{
public void add(E e);
public Iterator<E> iterator();
}
//自定义的泛型接口
public interface MyGenericInterface<T>{
void add(T t);
T get();
}
泛型接口使用格式:
1.定义实现类时,可以确定泛型的类型
public class MyInterfaceImpl implements MyGenericInterface<String>{
@Override
void add(String str){};
@Override
String get(){};
}//此时泛型T的值就是String类型
2.始终不确定泛型的类型,直到创建对象的时候才确定泛型类型
public class MyInterfaceImpl02<T> implements MyGenericInterface<T>{
@Override
void add(T t){};
@Override
T get(){};
}//创建对象的时候必须确定泛型类型