一、泛型
【引例】
在Dog类和Cat类添加角斗的方法:
狗与狗角斗,猫和锚角斗。
1、创建一个接口
2、Dog类实现接口
从上例可以看出,用父类作为接口方法的参数,在子类重写方法时,需要检查子类的真实类型并转型,否则就有可能发生类转换异常。我们可以将方法的接口方法的参数改为泛型,在子类重写方法时,就不需要进行类型检查了。
1.1 什么是泛型
泛型就是在设计时(在编写接口方法时)不需要指定接口方法引用类型参数的类型,在实现时(子类重写方法时)再指定接口方法引用类型参数的类型。即通过给类或接口增加引用类型参数,使得在使用该类时才需要指定引用类型参数的实际对应的类型。从而可以提高程序的灵活性,防止出现运行时类型错误,并可以避免数据的类型转换。比如,一个纸箱可以装苹果,也可以装桔子、玩具等,厂家在生产纸箱时并没有指定这个纸箱需要要装什么东西(可以装苹果、桔子、玩具等),如果是卖苹果商家需要用这个纸箱,就会在纸箱上贴上苹果的标签,我们就不会用这个纸箱去装桔子和玩具了。
1.2 泛型的应用
1、泛型的类定义
类名 <引用类型参数列表>
泛型的接口定义
接口名 <引用类型参数列表>
引用类型参数:用任意大写字母表示,多个参数用逗号分隔。
2、泛型实现
如上例,泛型规定了方法fight的对象为Dog类型,调用方法时只能传入Dog类型的对象,不需要检查对象的真实类型和转型了。
泛型的真实类型只能是引用类型,基本数据类型使用包装类型。
二、集合
【引例】学校每学期开设了Java、C++等多门课程供学生选修,每门课程选修的人数不限,统计每个学生的考试成绩。
1、每个学生选了多门课程?不确定。
2、共有多少个学生选修了课程?不确定。
如果用数组来保存选修的情况 ,数组的长度是固定的,而选修课程的学生人数,每个学生选修了多少课程无法确定,显然数组是不适合的。如果有一个数据结构,它的长度随着元素的增加或减少而变化,就可以解决这个问题了。像这样在程序运行时并不知道需要多少对象(元素个数)的情况下,可以使用Java集合。
Java集合为我们提供了一套性能优良、使用方便的接口和类,它们位于java.util包中
1、Collection:接口存储一组不唯一,无序的对象提供了对集合进行排序、遍历等多种算法实现。
2、Map:存储一组键值对象,提供key到value的映射。
2.1 List接口
List 接口存储一组不唯一,有序(插入顺序)的对象。List接口有2个常用的实现类:
- ArrayList实现了长度可变的数组,在内存中分配连续的空间。遍历元素和随机访问元素的效率比较高

- LinkedList采用链表存储方式。插入、删除元素时效率比较高

1、集合的定义
List是一个泛型接口。
List
List
2、List接口常用的方法
| 方法名 | 说 明 |
|---|---|
| boolean add(Object o) | 在列表的末尾顺序添加元素,起始索引位置从0开始 |
| void add(int index,Object o) | 在指定的索引位置添加元素。索引位置必须介于0和列表中元素个数之间 |
| int size() | 返回列表中的元素个数 |
| Object get(int index) | 返回指定索引位置处的元素。取出的元素是Object类型,使用前需要进行强制类型转换 |
| boolean contains(Object o) | 判断列表中是否存在指定元素 |
| boolean remove(Object o) | 从列表中删除元素 |
| Object remove(int index) | 从列表中删除指定位置元素,起始索引位置从0开始 |
【例2.1-01】
3、LinkedList的特殊方法
| 方法名 | 说 明 |
|---|---|
| void addFirst(Object o) | 在列表的首部添加元素 |
| void addLast(Object o) | 在列表的末尾添加元素 |
| Object getFirst() | 返回列表中的第一个元素 |
| Object getLast() | 返回列表中的最后一个元素 |
| Object removeFirst() | 删除并返回列表中的第一个元素 |
| Object removeLast() | 删除并返回列表中的最后一个元素 |
【例2.1-02】
【例2.1-03】完成引例
1、每个学生选修了多少课程


测试
2、统计共有多少学生选修课程,打印所有学生成绩



测试
2.2 Set接口
Set 接口存储一组唯一,无序的对象 。
无序:指的是元素不按照插入的顺序排序,是散列式排列的,所以没有编号,即不能用get(i)访问元素。
- HashSet集合的数据结构是哈希表,所以存储元素的时候使用的原色的hashCode方法来确定位置,如果位置相同,再通过元素的equals()方法判断内容是否相等。
- TreeSet为使用树型结构进行存储的Set接口提供了一个工具。如果存储的是基本数据类型、存储是会以“自然排序”的方式存储。如果的对象类型,当存储多个会存储出错,因为无法对对象进行排序,但是可以为这个类实现comparable接口,并实现它的compareTo()方法。
1、集合定义
Set
Set
2、HashSet常用方法
| 方法 | 功能描述 |
|---|---|
| public boolean add(E o) | 向集合添加指定元素 |
| public void clear() | 清空集合中所有元素 |
| public boolean contains(Object o) | 判断集合是否包含指定元素 |
| public boolean isEmpty() | 判断集合是否还有元素。如果集合不包含任何元素,则返回true |
| public Iterator iterator() | 返回对此集合中元素进行迭代的迭代器 |
| public boolean remove(Object o) | 删除集合中的元素 |
| public int size() | 返回此集合中的元素的个数 |
| public Object[] toArray | 将集合中的元素放到数组中,并返回该数组 |
【例2.2-01】用Set改写例2.1-01
代码略
3、TreeSet常用方法
| 方法 | 功能描述 |
|---|---|
| public E first() | 返回有序集合中第一个元素,即最小的那个元素 |
| public E last() | 返回有序集合中最后一个元素,即最大的那个元素 |
| public SortedSetsubSet(E fromElement,EtoElement) | 返回有序集合从fromElement(包括)到toElement (不包括)的元素 |
【例2.2-02】用TreeSet改写例2.2-01,发现了什么?
代码略
三、Map接口
Map接口专门处理键值映射数据的存储(key-value),可以根据键实现对值的操作,Map就像一个字典,我们也经常称之为字典。
- HashMap无序,即key是一个HashSet,值是一个List,是最常用的Map实现类。
- TreeMap默认为升序排序,即key是一个TreeSet。
3.1 HashMap
1、Map定义
Map的key和value都是泛型。
Map= new HashMap<>(); 
2、Map的常用方法
| 方法名 | 说 明 |
|---|---|
| Object put(Object key, Object val) | 以“键-值对”的方式进行存储 |
| Object get (Object key) | 根据键返回相关联的值,如果不存在指定的键,返回null |
| Object remove (Object key) | 删除由指定的键映射的“键-值对” |
| int size() | 返回元素个数 |
| Set keySet () | 返回键的集合 |
| Collection values () | 返回值的集合 |
| boolean containsKey (Object key) | 如果存在由指定的键映射的“键-值对”,返回true |
【例3.1-01】通过国家英文简称查找国家的中文全名。
【例3.1-02】根据宠物昵称查找对应宠物,如果找到,显示宠物信息,否则抛出异常 。
【练习】
1、将1-100之间所有的能被3和5整除的数加入到集合,并将第一个和最后一个元素删除。
2、主人领养了多只宠物,有可能是宠物狗,也有可能是企鹅,输出主人领养的宠物信息。
3、模拟百度翻译,用户输入英语单词,搜索出对应的中文,如果没有找到抛出异常。
4、打印如下表格的数据。
| 班级 | 学号 | 姓名 | 学分 |
|---|---|---|---|
| D01 | D0101 | 黄小明 | 20 |
| D0102 | 张兰 | 22 | |
| D02 | D0201 | 李英 | 20 |
| D0202 | 王峥嵘 | 24 | |
| D0203 | 刘小东 | 22 |
