泛型
1 泛型的含义
泛型是一种类型参数,专门用来保存类型用的。 就是用来对数据类型进行约束!
最早接触泛型是在ArrayList,这个E就是所谓的泛型了。使用ArrayList时,只要给E指定某一个类型,里面所有用到泛型的地方都会被指定对应的类型。

ArrayList list3 = new ArrayList() ; // E = Object
如果没有给泛型变量设定一个类型,默认表示Object 也就是上帝类!

2 使用泛型的好处
不用泛型带来的问题:
集合若不指定泛型,默认就是Object。存储的元素类型自动提升为Object类型。获取元素时得到的都是Object,若要调用特有方法需要转型,给我们编程带来麻烦.

使用泛型带来的好处:
可以在编译时就对类型做判断,避免不必要的类型转换操作,精简代码,也避免了因为类型转换导致的错误。

3 注意
泛型在代码运行时,泛型会被擦除。后面学习反射的时候,可以实现在代码运行的过程中添加其他类型的数据到集合。

泛型是什么?
泛型就是参数,专门用来保存引用数据类型
泛型有什么好处?
在编译时期会做类型的检查,可以有效避免在运行时类型强转的异常,对于程序员来讲不用额外的类型强转操作,简化代码。
泛型在运行时有什么特点?
只在编译期间起到作用
泛型在运行的时候,就会被擦除。

自定义泛型类
当一个类定义其属性的时候,不确定具体是什么类型时,就可以使用泛型表示该属性的类型。
1 定义格式
在类型名后面加上一对尖括号,里面定义泛型。一般使用一个英文大写字母表示,如果有多个泛型使用逗号分隔。

public class 类名<泛型名>{ //类型内部,就可以把泛型名当做是某一种类型使用了。}

2 泛型的指定
可以直接在创建对象时,指定类型和使用ArrayList一样: Student stu = new
ArrayList list = new ArrayList<>(); Student<>();
3 代码实践

定义一个人类,定义一个属性表示爱好,但是具体爱好是什么不清楚,可能是游泳,乒乓,篮球。
定义类时,什么时候可以使用泛型(使用场景)?
类中定义属性不知道具体类型时,就可以使用泛型。
类中如何定义泛型(格式) ?
public class 类名<泛型名>{ <>可以是任意一个大写字母,可定义多个 中间用,隔开。
}
泛型使用时,如何指定具体类型?
创建对象的时候可以具体指定泛型
自定义泛型接口
当定义接口时,内部方法中其参数类型,返回值类型不确定时,就可以使用泛型替代了。
1 定义格式
在类型名后面加上一对尖括号,里面定义泛型。一般使用一个英文大写字母表示,如果有多个泛型使用逗号分隔。
public interface 接口名<泛型名>{
public interface Collection{
** //类型内部,就可以把泛型名当做是某一种类型使用了。 public boolean add(E e);} } **

2 泛型的指定
可以在子类实现接口时,具体指定类型
如果子类也不确定类型,继续使用泛型指定,变成含有泛型的类使用。
什么时候使用泛型?
定义一个类型的时候,如果内部需要使用某一个数据不确定具体类型,就可以使用泛型。
定义接口泛型的格式?
接口名后面加上尖括号,里面定义泛型名
怎么给泛型接口指定泛型?
子类如果可以确定类型,在实现接口的时候,直接指定类型
子类如果不确定类型,继续使用泛型指定,回到泛型类的使用
自定义泛型方法
当定义方法时,方法中参数类型,返回值类型不确定时,就可以使用泛型替代了。
1 定义格式
可以在方法的返回值类型前,加上泛型
修饰符 <泛型名> 返回值类型 方法名(参数类别){
}
2 泛型的指定
调用含有泛型的方法时,传入的数据其类型就是泛型的类型
3 代码实践
定义存储字符串的ArrayList集合,将字符串的集合转换为字符串数组
泛型方法其泛型的定义格式?
修饰符后面,返回值前面定义泛型
什么时候可以确定方法中泛型的类型?

调用方法时传入数据,该数据是什么类型,泛型就是什么类型

泛型通配符介绍
当我们对泛型指定类型不是某一种特定类型,而是表达可以是任意类型,可以使用泛型通配符给定。
符号就是一个问号:? 表示任意类型,用来给泛型指定的一种通配值。

泛型通配符是什么?
问号(英文问号)
泛型通配符使用有什么注意事项?
泛型不支持多态
集合使用泛型通配符,方法参数含有泛型,就用不了。
2 泛型通配符结合集合使用

1. 泛型通配符结合集合使用一般在方法的参数中比较常见。
2. 在集合中泛型是不支持多态的,如果为了匹配任意类型,我们就会使用泛型通配符了。
3.方法内部使用该含有泛型通配符的集合时,要特别注意如下:内部类型会提升为Object类型。
集合类型的方法中参数如果携带泛型则无法使用。
方法中参数含有泛型,这个方法就用不了了!

3 代码实践
已知存在继承体系:Integer继承Number,Number继承Object。定义一个方法,方法的参数是一个ArrayList。要求可以接收ArrayList,ArrayList,ArrayList,ArrayList这些类型的数据。

泛型通配符是什么?
问号(英文问号)

泛型通配符使用有什么注意事项?
泛型不支持多态
集合使用泛型通配符,方法参数含有泛型,就用不了。

受限泛型
受限泛型是指,对泛型做了约束,给泛型指定类型时,只能是某个类型及其父类型或者某个类型及其子类型。

泛型的下限<? super 类型> //只能是某一类型,及其父类型,其他类型不支持
泛型的上限<? extends 类型> //只能是某一个类型,及其子类型,其他类型不支持

2 代码实践
基于上一个知识点,定义方法
show1方法,参数只接收元素类型是Number或者其父类型的集合
show2方法,参数只接收元素类型是Number或者其子类型的集合

泛型的上限格式和含义是什么?
<? extends 类型> 只能是本类型或者子类型
泛型的下限格式和含义是什么?
<? super 类型> 只能是本类型或者父类型,到顶了只能是Object

数据结构
1 数据结构介绍
数据结构是计算机存储、组织数据的方式。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法和索引技术有关。
2 常见的数据结构

队列
数组
链表
树(二叉树,二叉平衡树,红黑树)
哈希表(数组+链表+红黑树)

数据结构-栈
1 栈数据结构特点
栈(stack):是一种受限的线性表结构,不能在中间任何位置进行数据的操作,只能在指定的一端进行存或者取。

特点:先进后出,后进先出。
生活中中有哪些场景可以体现栈结构:
手枪的弹夹。最先压入的子弹,最后打出。
乒乓球桶。最先放进去的求,最后才能拿出。
名词解释:
压栈(入栈):将数据存入栈结构
弹栈(出栈):将数据弹出栈结构
数据结构-队列

2 队列数据结构的特点
队列(Queue )结构,也是一种线性表结构。要求数据只能一端存储,一端取出。

特点:先进先出。
生活中的场景:排队安检,食堂吃饭排队。

数据结构-数组
1 数组结构介绍
数组在内存中是由一片连续的空间组成。每个元素都是相邻的有索引,可以通过索引快速定位元素的位置。
数组结构是稳定的,一旦定义,结构就不能改变。如果要增删元素,需要借助新的数组,将老数组的元素拷贝到新数组中。

数组的特点:查询快,增删慢
2 数组元素的增删

新增元素:
需要创建一个新数组,将指定新元素存储在指定索引位置,再把原数组元素根据索引,复制到新数组对应索引的位置

删除元素:
需要创建一个新数组,把原数组元素根据索引,复制到新数组对应索引的位置,原数组中指定索引位置元素不复制到新数组中。

数组结构-链表

1 链表结构介绍
链表(linked list ),由一系列结点node(链表中每一个元素称为结点)组成,节点就是一个个的对象。节点对象在内存中无需连续空间,通过地址进行相连。
每个结点包括两个部分:
数据域:用来保存数据
指针域:存储地址,用来连接其他节点

2 单向链表
每个节点,只有下一个节点的地址

3 双向链表
每个节点,即有下一个节点的地址,又有上一个节点的地址

4 链表特点
链表在获取数据时不能像数组一样使用索引来定位获取,只能从开始节点位置或结束节点位置(双向链表)进行逐个查询,因此查询数据相较数组来讲是比较慢的。

链表在增删数据时无需新建新链表,摧毁旧链表。只要在局部位置进行地址的改变就可以,效率相比数组是交高效

简而言之,链表结构特点: 查询慢, 增删快

栈结构的特点?
先进后出
队列结构的特点?
先进先出
数组结构的特点
增删慢,查询快
链表结构的特点?
增删快,查询慢

List

List集合是Collection集合子类型,继承了所有Collection中功能,比Collection约束更加详细,严谨。
特点如下:
元素具备索引 【有索引】
元素可以重复存储(两个对象如果equals方法调用后返回true)【可重复】
元素的存取是有序的【有序】

ArrayList:底层结构就是数组【查询快,增删慢】
Vector:底层结构也是数组(线程安全,同步安全的,低效,用的就少)
LinkedList:底层是链表结构(双向链表)【查询慢,增删快】

3 List中常用的方法

List继承了Collection中所有方法,元素具备索引特性,因此新增了一些含有索引的特有方法,如下:
- public void add(int index, E element): 将指定的元素,添加到该集合中的指定位置上。
- public E get(int index):返回集合中指定位置的元素。
- public E remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素。
- public E set(int index, E element):用指定元素替换集合中指定位置的元素,返回值的更新前的元素。

List集合有什么特点?
1. 有序 2. 可重复的 3. 有索引
List集合有哪些常用的子类及底层数据结构是啥?
ArrayList:数组结构
LinkedList:双向链表
Vector:数组结构
List集合有哪些常用的特有方法?
add remove set get

LinkedList集合
LinkedList底层结构是双向链表。每个节点有三个部分的数据,一个是保存元素数据,一个是保存前一个节点的地址,一个是保存后一个节点的地址。可以双向查询,效率会比单向链表高。

2 LinkedList特有方法
public void addFirst(E e):将指定元素插入此列表的开头。public void addLast(E e):将指定元素添加到此列表的结尾。public E getFirst():返回此列表的第一个元素。public E getLast():返回此列表的最后一个元素。public E removeFirst():移除并返回此列表的第一个元素。public E removeLast():移除并返回此列表的最后一个元素。public E pop():从此列表所表示的堆栈处弹出一个元素。(底层实现就是removeFist)public void push(E e):将元素推入此列表所表示的堆栈。(底层就是addFirst)
LinkedList内部结构是什么?**

双向链表结构

LinkedList有哪些特有方法?

addFirst
addLast
removeFirst
removeLast
getFirst
getLast
pop
push

代码实现!

人员类(Person):
|—学生类(Student)
|—Java学生类(JavaStudent)
|—UI学生类(UIStudent)
|—教师类(Teacher)
|—Java教师类(JavaTeacher)
|—UI教师类(UITeacher)
- 请按上述要求定义类,并实现继承关系即可(不需要定义类成员,定义空类表示关系即可)
- 请按以下格式和要求定义测试类和方法:
public class Test1{
public static void main(String[] args){
ArrayList list1 = new ArrayList<>();
ArrayList list2 = new ArrayList<>();
ArrayList list3 = new ArrayList<>();
ArrayList list4 = new ArrayList<>();
ArrayList list5 = new ArrayList<>();
ArrayList list6 = new ArrayList<>();
ArrayList list7 = new ArrayList<>();
ArrayList list8 = new ArrayList<>();
//请测试哪些集合可以调用print1()方法
//请测试哪些集合可以调用print2()方法
//请测试哪些集合可以调用print3()方法
//请测试哪些集合可以调用print4()方法
}
//要求:参数可以接收任何泛型的ArrayList参数
public static void print1(ArrayList<______________> list){

}
//要求:参数可以接收任何Person及其子类泛型的ArrayList参数
public static void print2(ArrayList<______________> list){
}
//要求:参数可以接收任何Student及其子类泛型的ArrayList参数
public static void print3(ArrayList<______________> list){
}
//要求:参数可以接收任何Java学员,及其父类泛型的ArrayList参数
public static void print4(ArrayList<______________> list){
}

}
//要求:参数可以接收任何泛型的ArrayList参数
public static void print1(ArrayList<?> list){

}

//要求:参数可以接收任何Person及其子类泛型的ArrayList参数
public static void print2(ArrayList<? extends Person> list){
}
//要求:参数可以接收任何Student及其子类泛型的ArrayList参数
public static void print3(ArrayList<? extends Student> list){
}
//要求:参数可以接收任何Java学员,及其父类泛型的ArrayList参数
public static void print4(ArrayList<? super Java> list){
}
```

请写出你所知道的数据结构,至少5种。

```java
栈, 队列 , 数组 , 链表 . 二叉树 , 哈希表
```

写出栈结构、队列结构的特点

```
栈: 先进后出 队列 : 先进先出
```

请写出数组结构的特点;

```
数组: 查询快 , 增删慢
```

请写出链表结构的特点

```
链表: 查询慢 , 增删快
```

需求:创建一个ArrayList集合,添加5个整数,然后使用不同的方式遍历这些数据。

1. 自增for循环遍历

2. 迭代器遍历

3. 增强for循环遍历

public static void main(String[] args) { ArrayListlist=new ArrayList<>(); list.add(40); list.add(50); list.add(70); list.add(90); list.add(100);** Integer []arr={40,50,70,90,100}; for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } for (int a : arr) { System.out.println(“a = “ + a); } Iterator iter = list.iterator(); while (iter.hasNext()){ Integer next = iter.next(); System.out.println(“next = “ + next); } }}

需求:定义一个方法int listTest(ArrayList<Integer> list, Integer num),要求实现返回num在list里面第一次出现的索引,如果num没出现过返回-1。

思路:

- 在方法中遍历list集合,判断是否是num,如果是返回索引,遍历完成后没有发现数据直接返回-1
- 对象比较用equals- 在测试类中进行测试
public class Demo03 { public static void main(String[] args) { ArrayList list = new ArrayList<>(); list.add(40); list.add(50); list.add(60); list.add(70); list.add(80); System.out.println(listTest(list,5)); } public static int listTest(ArrayList list, Integer num) { for (int i = 0; i < list.size(); i++) { Integer integer = list.get(i); if (integer.equals(num)) { return i; } } return -1; }}**

1. 定义一个学生类Student,包含三个属性姓名、年龄、性别,私有成员变量,生成无参,有参构造方法,生成get/set方法。

2. 创建三个学生对象存入ArrayList集合中。

3. 找出年龄最大的学生,然后将该对象的姓名变为:小猪佩奇。

4. 遍历集合输出对象属性信息。(输出格式如:姓名:张三, 年龄:23, 性别:男)

public class Student {
private String name;
private int age;
private String sex;

public Student() {
}

public Student(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return “Student{“ +
“name=’” + name + ‘\’’ +
“, age=” + age +
“, sex=’” + sex + ‘\’’ +
‘}’;
}
}

public class StudentTest02 { public static void main(String[] args) { ArrayListS1=new ArrayList< >( ); Student01 s1=new Student01(“李四”,20,”男”); Student01 s2=new Student01(“和二”,26,”男”); Student01 s3=new Student01(“小花”,19,”女”); S1.add(s1); S1.add(s2); S1.add(s3); int max=0; Student01 maxSTU=S1.get(0); for (int i = 0; i < S1.size(); i++) { Student01 s=S1.get(i); if(s.getAge()>maxSTU.getAge()){ max= i; maxSTU=s; }} S1.get(max).setName(“小猪佩奇”); for (Student01 student01:S1){ System.out.println(“student01 = “ + student01); }}}

请编写main()方法,按以下要求顺序:
1. 定义一个Set集合,并存储以下数据:刘备,关羽,张飞,刘备,张飞
1. 打印集合大小
1. 使用迭代器遍历集合,并打印每个元素
1. 使用增强for遍历集合,并打印每个元素
思路:Set集合具有去重效果
public class Demo04 { public static void main(String[] args) { HashSeths=new HashSet<>(); hs.add(“刘备”); hs.add(“关羽”); hs.add(“张飞”); hs.add(“刘备”); hs.add(“张飞”); System.out.println(hs.size());** Iteratorit=hs.iterator(); while (it.hasNext()){ String s= it.next(); System.out.println(s); }** for (String h:hs){ System.out.println(h); }
请按以下要求顺序编码:

1. 定义一个可以存储“整数”的LinkedHashSet对象
2. 存储以下整数: 20,30,50,10,30,20
3. 打印集合大小。为什么跟存入的数量不一致?
4. 使用增强for遍历集合,打印大于25的元素
public class Test01 { public static void main(String[] args) { LinkedHashSet list = new LinkedHashSet<>(); list.add(20); list.add(30); list.add(50); list.add(10); list.add(30); list.add(20); System.out.println(list); for (Integer i : list) { if (i > 25) { System.out.println(“i = “ + i);
}}}}

为什么打印集合数量跟存入的数量不一致?

因为底层是哈希表结构+链表结构 , 哈希表保证元素唯一 , 链表保证元素顺序

day05 泛型,数据结构,List,Set

今日目标

  • 泛型使用
  • 数据结构
  • List
  • Set

1 泛型

1.1 泛型的介绍

  • 泛型是一种类型参数,专门用来保存类型用的
    • 最早接触泛型是在ArrayList,这个E就是所谓的泛型了。使用ArrayList时,只要给E指定某一个类型,里面所有用到泛型的地方都会被指定对应的类型

1.2 使用泛型的好处

  • 不用泛型带来的问题
    • 集合若不指定泛型,默认就是Object。存储的元素类型自动提升为Object类型。获取元素时得到的都是Object,若要调用特有方法需要转型,给我们编程带来麻烦.
  • 使用泛型带来的好处
    • 可以在编译时就对类型做判断,避免不必要的类型转换操作,精简代码,也避免了因为类型转换导致的代码异常
  1. //泛型没有指定类型,默认就是Object
  2. ArrayList list = new ArrayList();
  3. list.add("Hello");
  4. list.add("World");
  5. list.add(100);
  6. list.add(false);
  7. //集合中的数据就比较混乱,会给获取数据带来麻烦
  8. for (Object obj : list) {
  9. String str = (String) obj;
  10. //当遍历到非String类型数据,就会报异常出错
  11. System.out.println(str + "长度为:" + str.length());
  12. }

1.3 泛型的注意事项

  • 泛型在代码运行时,泛型会被擦除。后面学习反射的时候,可以实现在代码运行的过程中添加其他类型的数据到集合
    • 泛型只在编译时期限定数据的类型 , 在运行时期会被擦除

1.4 自定义泛型类

  • 当一个类定义其属性的时候,不确定具体是什么类型时,就可以使用泛型表示该属性的类型
  • 定义的格式
    • 在类型名后面加上一对尖括号,里面定义泛型。一般使用一个英文大写字母表示,如果有多个泛型使用逗号分隔
    • public class 类名<泛型名>{ … }
      1. 举例 :
      2. public class Student<X,Y>{
      3. X xObj;
      4. }
  • 泛型的确定
    • 当创建此泛型类是 , 确定泛型类中泛型的具体数据类型
  • 练习
  1. package com.itheima.genericity_demo.genericity_class;
  2. import java.time.Period;
  3. /*
  4. 需求 : 定义一个人类,定义一个属性表示爱好,但是具体爱好是什么不清楚,可能是游泳,乒乓,篮球。
  5. */
  6. public class GenericityDemo {
  7. public static void main(String[] args) {
  8. Person<BasketBall> person = new Person<>();
  9. person.setHobby(new BasketBall());
  10. Person<Swim> person2 = new Person<>();
  11. person2.setHobby(new Swim());
  12. Person person3 = new Person<>();// 如果没有指定泛型 , 那么默认使用Object数据类型
  13. }
  14. }
  15. class Person<H> {
  16. // 定义属性表达爱好
  17. private H hobby;
  18. public H getHobby() {
  19. return hobby;
  20. }
  21. public void setHobby(H hobby) {
  22. this.hobby = hobby;
  23. }
  24. }
  25. class Swim {
  26. }
  27. class PingPang {
  28. }
  29. class BasketBall {
  30. }

1.3 自定义泛型接口

  • 当定义接口时,内部方法中其参数类型,返回值类型不确定时,就可以使用泛型替代了。
  • 定义泛型接口
    • 在接口后面加一对尖括号 , 尖括号中定义泛型 , 一般使用大写字母表示, 多个泛型用逗号分隔
    • public interface<泛型名> { … }
    • 举例 :
      1. public interface Collection<E>{
      2. public boolean add(E e);
      3. }
  • 泛型的确定
    • 实现类去指定泛型接口的泛型
    • 实现了不去指定泛型接口的泛型 , 进行延续泛型 , 回到泛型类的使用
  1. package com.itheima.genericity_demo.genericity_interface;
  2. /*
  3. 需求:
  4. 模拟一个Collection接口,表示集合,集合操作的数据不确定。
  5. 定义一个接口MyCollection具体表示。
  6. */
  7. // 泛型接口
  8. public interface MyCollection<E> {
  9. // 添加功能
  10. public abstract void add(E e);
  11. // 删除功能
  12. public abstract void remove(E e);
  13. }
  14. // 指定泛型的第一种方式 : 让实现类去指定接口的泛型
  15. class MyCollectionImpl1 implements MyCollection<String>{
  16. @Override
  17. public void add(String s) {
  18. }
  19. @Override
  20. public void remove(String s) {
  21. }
  22. }
  23. // 指定泛型的第二种方式 : 实现类不确定泛型,延续泛型,回到泛型类的使用
  24. class MyCollectionImpl2<E> implements MyCollection<E>{
  25. @Override
  26. public void add(E a) {
  27. }
  28. @Override
  29. public void remove(E a) {
  30. }
  31. }

1.4 自定义泛型方法

  • 当定义方法时,方法中参数类型,返回值类型不确定时,就可以使用泛型替代了
  • 泛型方法的定义
    • 可以在方法的返回值类型前定义泛型
    • 格式 : public <泛型名> 返回值类型 方法名(参数列表){ … }
    • 举例 : public void show(T t) { … }
  • 泛型的确定
    • 当调用一个泛型方法 , 传入的参数是什么类型, 那么泛型就会被确定
  • 练习
    ```java package com.itheima.genericity_demo.genericity_method;

import java.util.ArrayList; import java.util.Arrays;

public class Test { public static void main(String[] args) { // Collection集合中 : public T[] toArray(T[] a) : 把集合中的内容存储到一个数组中 , 进行返回 ArrayList list = new ArrayList<>(); list.add(“abc”); list.add(“ads”); list.add(“qwe”); String[] array = list.toArray(new String[list.size()]); System.out.println(Arrays.toString(array)); }

  1. // 接收一个集合 , 往集合中添加三个待指定类型的元素
  2. public static <X> void addElement(ArrayList<X> list, X x1, X x2, X x3) {
  3. list.add(x1);
  4. list.add(x2);
  5. list.add(x3);
  6. }

}

  1. <a name="7e98fb7f"></a>
  2. ### 1.5 通配符
  3. - 当我们对泛型的类型确定不了,而是表达的可以是任意类型,可以使用泛型通配符给定<br />符号就是一个问号:? 表示任意类型,用来给泛型指定的一种通配值。如下
  4. ```java
  5. public static void shuffle(List<?> list){
  6. //…
  7. }
  8. 说明:该方法时来自工具类Collections中的一个方法,用来对存储任意类型数据的List集合进行乱序
  • 泛型通配符结合集合使用
    • 泛型通配符搭配集合使用一般在方法的参数中比较常见。在集合中泛型是不支持多态的,如果为了匹配任意类型,我们就会使用泛型通配符了。
    • 方法中的参数是一个集合,集合如果携带了通配符,要特别注意如下
      • 集合的类型会提升为Object类型
      • 方法中的参数是一个集合,集合如果携带了通配符,那么此集合不能进行添加和修改操作 , 可以删除和获取 ```java package com.itheima.genericity_demo;

import java.util.ArrayList; import java.util.List;

public class Demo { public static void main(String[] args) { ArrayList list = new ArrayList<>(); list.add(“abc”); list.add(“asd”); list.add(“qwe”); // 方法的参数是一个集合 , 集合的泛型是一个通配符 , 可以接受任意类型元素的集合 show(list); }

  1. public static void show(List<?> list) {
  2. // 如果集合的泛型是一个通配符 , 那么集合中元素以Object类型存在
  3. Object o = list.get(0);
  4. // 如果集合的泛型是一个通配符 , 那么此集合不能进行添加和修改操作 , 可以删除和获取
  5. // list.add(??);
  6. // 删除可以
  7. list.remove(0);
  8. // 获取元素可以
  9. for (Object o1 : list) {
  10. System.out.println(o1);
  11. }
  12. }

}

  1. ```java
  2. package com.itheima.genericity_demo;
  3. import java.util.ArrayList;
  4. /*
  5. 已知存在继承体系:Integer继承Number,Number继承Object。
  6. 定义一个方法,方法的参数是一个ArrayList。
  7. 要求可以接收ArrayList<Integer>,ArrayList<Number>,ArrayList<Object>,ArrayList<String>这些类型的数据。
  8. 结论 : 具体类型的集合,不支持多态 , 要想接收任意类型集合 , 需要使通配符集合
  9. */
  10. public class Test1 {
  11. public static void main(String[] args) {
  12. ArrayList<Integer> list1 = new ArrayList<>();
  13. ArrayList<Number> list2 = new ArrayList<>();
  14. ArrayList<String> list3 = new ArrayList<>();
  15. ArrayList<Object> list4 = new ArrayList<>();
  16. useList5(list1);
  17. useList5(list2);
  18. useList5(list3);
  19. useList5(list4);
  20. }
  21. // 此方法只能接收存储Integer类型数据的集合
  22. public static void useList1(ArrayList<Integer> list) {
  23. }
  24. // 此方法只能接收存储Number类型数据的集合
  25. public static void useList2(ArrayList<Number> list) {
  26. }
  27. // 此方法只能接收存储String类型数据的集合
  28. public static void useList3(ArrayList<String> list) {
  29. }
  30. // 此方法只能接收存储Object类型数据的集合
  31. public static void useList4(ArrayList<Object> list) {
  32. }
  33. public static void useList5(ArrayList<?> list) {
  34. }
  35. }

1.6 受限泛型

  • 受限泛型是指,在使用通配符的过程中 , 对泛型做了约束,给泛型指定类型时,只能是某个类型父类型或者子类型
  • 分类 :
    • 泛型的下限 :
      • //只能是某一类型,及其父类型,其他类型不支持
    • 泛型的上限 :
      • //只能是某一个类型,及其子类型,其他类型不支持 ```java package com.itheima.genericity_demo.wildcard_demo;

import java.util.ArrayList;

/* wildcardCharacter

基于上一个知识点,定义方法 show1方法,参数只接收元素类型是Number或者其父类型的集合 show2方法,参数只接收元素类型是Number或者其子类型的集合

*/ public class Test2 { public static void main(String[] args) { ArrayList list1 = new ArrayList<>(); ArrayList list2 = new ArrayList<>(); ArrayList list3 = new ArrayList<>();

  1. show1(list3);
  2. show1(list2);
  3. show2(list2);
  4. show2(list1);
  5. }
  6. // 此方法可以接受集合中存储的是Number或者Number的父类型 , 下限泛型
  7. public static void show1(ArrayList<? super Number> list) {
  8. }
  9. // 此方法可以接受集合中存储的是Number或者Number的子类型 , 上限泛型
  10. public static void show2(ArrayList<? extends Number> list) {
  11. }

} ```

2 数据结构

  • 栈结构 : 先进后出
  • 队列结构 : 先进先出
  • 数组结构 : 查询快 , 增删慢
  • 链表结构 : 查询慢 , 增删快
  • 二叉树
    • 二叉树 : 每个节点最多有两个子节点
    • 二茬查找树 : 每个节点的左子节点比当前节点小 , 右子节点比当前节点大
    • 二茬平衡树 : 在查找树的基础上, 每个节点左右子树的高度不超过1
    • 红黑树 :
      • 每一个节点或是红色的,或者是黑色的
      • 根节点必须是黑色
      • 如果一个节点没有子节点或者父节点,则该节点相应的指针属性值为Nil,这些Nil视为叶节点,每个叶节点(Nil)是黑色的
      • 不能出现两个红色节点相连的情况
      • 对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点
      • 添加元素 :
  • 哈希表结构 :
    • 哈希值:是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
    • Object类中有一个方法可以获取对象的哈希值
      public int hashCode():返回对象的哈希码值
    • 对象的哈希值特点
      • 同一个对象多次调用hashCode()方法返回的哈希值是相同的
      • 默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同

3 List集合

  • List集合是Collection集合子类型,继承了所有Collection中功能,同时List增加了带索引的功能
  • 特点 :
    • 元素的存取是有序的【有序】
    • 元素具备索引 【有索引】
    • 元素可以重复存储【可重复】
  • 常见的子类
    • ArrayList:底层结构就是数组【查询快,增删慢】
    • Vector:底层结构也是数组(线程安全,同步安全的,低效,用的就少)
    • LinkedList:底层是链表结构(双向链表)【查询慢,增删快】
  • List中常用的方法
    • public void add(int index, E element): 将指定的元素,添加到该集合中的指定位置上。
    • public E get(int index):返回集合中指定位置的元素
    • public E remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素。\
    • public E set(int index, E element):用指定元素替换集合中指定位置的元素,返回值的更新前的元素
  • LinkedList类
    • LinkedList底层结构是双向链表。每个节点有三个部分的数据,一个是保存元素数据,一个是保存前一个节点的地址,一个是保存后一个节点的地址。可以双向查询,效率会比单向链表高。
    • LinkedList特有方法
      • public void addFirst(E e):将指定元素插入此列表的开头。
      • public void addLast(E e):将指定元素添加到此列表的结尾。
      • public E getFirst():返回此列表的第一个元素。
      • public E getLast():返回此列表的最后一个元素。
      • public E removeFirst():移除并返回此列表的第一个元素。
      • public E removeLast():移除并返回此列表的最后一个元素。

4 Set集合

  • Set集合也是Collection集合的子类型,没有特有方法。Set比Collection定义更严谨
  • 特点 :
    • 元素不能保证插入和取出顺序(无序)
    • 元素是没有索引的(无索引)
    • 元素唯一(元素唯一)
  • Set常用子类
    • HashSet:底层由HashMap,底层结构哈希表结构。
      去重,无索引,无序。
      哈希表结构的集合,操作效率会非常高。
    • LinkedHashSet:底层结构链表加哈希表结构。
      具有哈希表表结构的特点,也具有链表的特点。
    • TreeSet:底层是有TreeMap,底层数据结构 红黑树。
      去重,让存入的元素具有排序(升序排序)