JavaSE进阶——Day05 该篇主要讲解Java中的泛型、数据结构、List集合和Set集合
泛型
什么是泛型?
是一种或类型参数,可以来设置存储数据类型
泛型解决程序中的什么问题?
泛型如何使用?
泛型类
1 2 3 4 5 6 7 8 9 10 11
| public class 类名<E>{ }
public class 泛型类<T>{ private T 变量; }
泛型类<Integer> 对象引用 = new 泛型类<Integer>(); 泛型类<String> 对象引用 = new 泛型类<String>();
|
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| package io.github.ethanliu6.genericity;
public class Demo01 { public static void main(String[] args) { GenericityClass<String> gc1 = new GenericityClass<>(); gc1.setObj("Ethan Love Qiu"); System.out.println(gc1.getObj());
GenericityClass<Integer> gc2 = new GenericityClass<>(); gc2.setObj(8888); System.out.println(gc2.getObj());
} }
class GenericityClass<T> { private T obj;
public T getObj() { return obj; }
public void setObj(T obj) { this.obj = obj; } }
|
泛型接口
当不确定接口中某个方法参数使用什么类型或者方法返回值类型时,可以使用泛型表示
1 2 3 4 5 6 7
| public interface 泛型接口<E>{ public void method(E e){ } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class 子类 implements 泛型接口<String> { @Override public void method(String e) { } }
public class 子类<E> implements 泛型接口<E> { public void method(E e){ } }
注意:在创建子类对象时,指定类型 子类<Integer> 子类引用名 = new 子类<>();
|
泛型方法
当前类没有声明为泛型类,当方法不知道参数类型或者返回值类型时,使用泛型方法
1 2 3 4
| 修饰符号 <泛型> 返回值类型 方法名(<参数泛型> 参数1, ……){ }
|
1 2 3 4
| public <T> method(<E> param){ }
|
泛型梳理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| 基础泛型的定义: 1、泛型类 2、泛型接口 3、泛型方法
问题:开发时选择哪个泛型定义? 第1,先明确要定义的是接口还是类 当类中的成员变量,在不确定具体使用哪种类型时,可以使用:泛型 表示类型 当接口中方法,在不确定方法参数类型或方法返回值类型时,可以使用:泛型 表示类型 第2,在编写工具类时,工具类中的方法参数或方法返回值,不确定具体类型, 可以使用: 泛型
问题:泛型定义的语法
public class 类名<T,E,X,Y>{ private T name; private E a; private X n; private Y m;
public 类名(T name , E a , X n ,Y m){ }
} new 类名<String,Integer,Double,Student>();
public interface 接口名<T,E>{ }
public <T> T 方法名(T 参数名){ }
问题: 怎么明确泛型指定的具体类型(指定泛型上的类型)
类名<String> 对象 = new 类名<>();
interface 接口<T>{ public void method(T n); public T get(); } class 子类 implements 接口<Integer>{ public void method(Integer n){ } public Integer get(){ } }
class 子类<T> implements 接口<T>{ public void method(T n){ } public T get(){ } }
public class 类{
public <T> T getInstance(T param){ }
} Student stu = 类对象.getInstance( new Student() )
|
泛型通配符
- 泛型通配符:
<?>(任意类型)
- 通常在开发中,
?与泛型的上下限一起使用
受限泛型
泛型下限:
1 2 3 4 5
| <? super 最小类型> ?可以是该最小类型 ?也可以是该类型的父类型
|
泛型上限:
1 2 3 4 5
| <? extends 最大类型>
?可以是该最大类型 ?也可以是该最大类型的子类型
|
例如:
![image-20240420173727772]()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| package io.github.ethanliu6.genericity.demo03;
import java.util.ArrayList;
public class Test2 { public static void main(String[] args) { ArrayList<Person> people = new ArrayList<>(); people.add(new Student(126, "202234004026")); people.add(new Worker()); show1(people); show2(people);
System.out.println("\n+++++++++++++++++\n"); ArrayList<Worker> workers = new ArrayList<>(); workers.add(new Worker()); show1(workers); }
public static void show1(ArrayList<? extends Person> people) { System.out.println("show1是泛型上限"); }
public static void show2(ArrayList<? super Student> E){ System.out.println("show2是泛型下限"); } }
|
数据结构
这里只是简单的学习数据结构,并非408中的系统性数据结构
数据结构的认识
数据结构:数据存储时的一种排列方式
类型:
栈(先进后出)
队列(先进先出)//数组就是这种方式
数组结构:
数组在内存中的体现是一块连续存储数据的空间
特点是查询快、增删元素慢
ArrayList集合底层就是使用:数组结构
栈
队列
树
平衡二叉树
红黑树
List集合
Java语言中集合体系划分:
java.util.Collection集合: 是一个接口(无法实例化)
- java.util.List集合(接口)
- 常用子类:ArrayList 、 LinkedList
- java.util.Set集合(接口)
![image-20240420193210344]()
java.util.List集合:
- 带有索引
- 存储的元素的顺序和获取元素的顺序一致
- 可以存储重复元素
因为List集合可以使用索引,故围绕着索引,设计很多API方法:
1 2 3 4 5 6 7 8 9 10 11 12
| List集合.add( 索引 , 元素值)
List集合.set( 索引 , 元素值)
List集合.remove(索引)
List集合.get(索引);
|
ArrayList集合:
- 实现List接口(List接口中的所有功能都有)
- 底层使用:数组
链表结构:
在内存中是使用==节点==来存储数据
链表:有头、有尾
- 分类:
- 单向链表:只能从头到尾
- 双向链表:可以从头到尾,也可以从尾到头 (提高查询效率)
- 代表集合类:LinkedList
LinkedList集合:
实现List接口
底层使用:双向链表(有头有尾)
特有方法都围绕着链表头和尾设计
1 2 3 4 5 6 7 8 9 10 11
| addFirst( 元素 ) addLast( 元素 )
removeFirst() removeLast()
getFirst() getLast()
|
Set集合
Collection集合
List集合
- 有索引
- 存取元素有序
- 可能存储重复元素
Set集合
- 没有索引
- 存取元素不保证顺序
- 不允许存储重复元素
Set集合中方法全部来自Collection集合
Set集合的子类:
HashSet集合
特点:
- 没有索引
- 存取元素不保证顺序
- 不能存储重复元素
- 底层使用:哈希表结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| package io.github.ethanliu6.set;
import java.util.HashSet; import java.util.Objects;
public class HashSetDemo1 { public static void main(String[] args) { HashSet<Person> peopleSet = new HashSet<>();
peopleSet.add(new Person("Qiu Zhu", 21)); peopleSet.add(new Person("Ethan Liu", 21)); peopleSet.add(new Person("Qiu Zhu", 21));
for (Person person : peopleSet) { System.out.println(person); } }
}
class Person { private String name; private int age;
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return age == person.age && Objects.equals(name, person.name); }
@Override public int hashCode() { return Objects.hash(name, age); }
@Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; }
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 Person(String name, int age) { this.name = name; this.age = age; }
public Person() { } }
|
- LinkedHashSet集合
- TreeSet集合
哈希表数据结构:
Set集合:
HashSet
- 底层:哈希表结构
- 特点:
- 不能存储重复元素
- 没有索引
- 存取元素顺序不保证一致
LinkedHashSet
特点:
- 没有索引
- 不能存储重复元素
- 存取元素顺序一致
底层:哈希表+链表(保证存储元素的顺序)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package io.github.ethanliu6.set;
import java.util.LinkedHashSet;
public class LinkedHashSetDemo1 { public static void main(String[] args) { LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("Qiu"); linkedHashSet.add("Ethan"); linkedHashSet.add("Qiu"); linkedHashSet.add("Liu");
for (String s : linkedHashSet) { System.out.println(s); } } }
|