文章内容输出来源:拉勾教育大数据开发高薪训练营
一、集合的基本概念
当需要在Java程序中记录单个数据内容时,则声明一个变量。
当需要在Java程序中记录多个类型相同的数据内容时,声明一个一维数组。
当需要在Java程序中记录多个类型不同的数据内容时,则创建一个对象。
当需要在Java程序中记录多个类型相同的对象数据时,创建一个对象数组。
当需要在Java程序中记录多个类型不同的对象数据时,则准备一个集合。
二、单列集合的体系结构
三、Collection集合
java.util.Collection接口是List接口、Queue 接口以及Set接口的父接口,因此该接口里定义的方法既可用于操作List集合,也可用于操作Queue集合和Set集合。
方法声明 | 功能介绍 |
---|---|
public boolean add(E e); | 把给定的对象添加到当前集合中 |
public void clear(); | 清空集合中所有的元素 |
public boolean remove(Object o);
| 把给定的对象在当前集合中删除 |
public boolean contains(Object o); |
判断是否包含指定对象
|
public int size(); |
返回包含对象的个数
|
public boolean isEmpty()
|
判断是否为空
|
public Object[] toArray()
|
将集合转换为数组
|
四、Iterator接口(迭代器)
java.util.Iterator接口主要用于描述迭代器对象,可以遍历Collection集合中的所有元素。
java.util.Collection接口继承Iterator接口,因此所有实现Collection接口的实现类都可以使用该迭代器对象。
方法声明 | 功能介绍 |
boolean hasNext()
|
判断集合中是否有可以迭代
/
访问的元素
|
E next()
|
用于取出一个元素并指向下一个元素
|
void remove()
|
用于删除访问到的最后一个元素
|
迭代器的实现原理:
在调用Iterator的next方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next方法后,迭代器的索引会向后移动一位,指向第一个元素并将该元素返回,当再次调用next方法时,迭代器的索引会指向第二个元素并将该元素返回,依此类推,直到hasNext方法返回false,表示到达了集合的末尾,终止对元素的遍历。
五、for each循环
可以应用数组和集合的遍历,简化版的迭代器;
格式:for (元素类型 变量名 : 数组/集合名) { ... }
六、泛型
6.1 基本概念:
通常情况下集合中可以存放不同类型的对象,是因为将所有对象都看做Object类型放入的,因此从集合中取出元素时也是Object类 型,为了表达该元素真实的数据类型,则需要强制类型转换,而强制类型转换可能会引发类型转换异常。
为了避免上述错误的发生,从Java5开始增加泛型机制,也就是在集合名称的右侧使用<数据类型>的方式来明确要求该集合中可以存放的元素类型,若放入其它类型的元素则编译报错。
6.2 使用泛型的好处:
a. 将运行时期的ClassCastException,转移到了编译时期变成了编译失败;
b. 避免了类型强转的麻烦。
6.3 泛型的底层原理:
泛型的本质就是参数化类型,也就是让数据类型作为参数传递,其中E相当于形式参数负责占位,而使用集合时<>中的数据类型相当于实际参数,用于给形式参数E进行初始化,从而使得集合中所有的E被实际参数替换,由于实际参数可以传递各种各样广泛的数据类型,因此得名为泛型。
具体如下:
6.4 自定义泛型类:
泛型类和普通类的区别就是类名后面添加了类型参数列表,可以有多个类型参数,如:<E, T, .. >;
实例化泛型类时应该指定具体的数据类型,并且是引用数据类型而不是基本数据类型。
父类有泛型,子类可以选择保留泛型也可以选择指定泛型类型。
子类必须是“富二代”,子类除了指定或保留父类的泛型,还可以增加自己的泛型。
泛型中的继承:如果B是A的一个子类或子接口,而G是具有泛型声明的类或接口,则G并不是G的子类型!
比如:String是Object的子类,但是List<Integer>并不是List<Integer>的子类。
6.5 自定义泛型方法:
泛型方法就是我们输入参数的时候,输入的是泛型参数,而不是具体的参数。我们在调用这个泛型方法的时需要对泛型参数进行实例化。
格式:修饰符 <代表泛型的变量> 返回值类型 方法名(参数){ }
在静态方法中使用泛型参数的时候,需要我们把静态方法定义为泛型方法。
具体如下:
// 定义泛型方法
public class MyGenericMethod {
public <MVP> void show(MVP mvp) {
System.out.println(mvp.getClass());
}
public <MVP> MVP show2(MVP mvp) {
return mvp;
}
}
// 调用泛型方法,在调用方法时,确定泛型的类型
public class GenericMethodDemo {
public static void main(String[] args) {
// 创建对象
MyGenericMethod mm = new MyGenericMethod();
// 演示看方法提示
mm.show("aaa");
mm.show(123);
mm.show(12.45);
}
}
6.6 定义泛型接口:
格式:修饰符 interface 接口名 <代表泛型的变量> { }
如:
// 泛型接口 public interface MyGenericInterface<E>{ public abstract void add(E e); public abstract E getE(); }
使用方法:
a. 定义类时确定泛型的类型;
// 定义类时确定泛型类型 public class MyImp1 implements MyGenericInterface<String> { @Override public void add(String e) { // 省略... } @Override public String getE() { return null; } }
b. 始终不确定泛型的类型,直到创建对象时,确定泛型的类型;
// 始终不确定泛型的类型 class MyImp2<E> implements MyGenericInterface<E> { @Override public void add(E e) { // 省略... } @Override public E getE() { return null; } } // 直到创建对象时,确定泛型的类型 public class GenericInterface { public static void main(String[] args) { MyImp2<String> my = new MyImp2<String>(); my.add("aa"); } }
6.7 泛型通配符:
不知道使用什么类型来接收的时候,此时可以使用 ? , ? 表示未知通配符。
泛型的上限与下限:
泛型的上限:
格式: 类型名称 <? extends 类> 对象名称
意义: 只能接受该类型及其子类
泛型的下限:
格式:类型名称 <? super 类> 对象名称
意义: 只能接受该类型及其父类