Java基础
泛型
泛型,是一种让类和方法可以操作任意类型的参数的机制,而不必在编译时指定具体的类型。泛型提高了代码的可重用性、类型安全性和可读性。
常见泛型使用场景
- 集合类
集合框架中的类(如ArrayList
、LinkedList
、HashMap
等)大量使用了泛型。
List<String> stringList = new ArrayList<>();
Map<String, Integer> map = new HashMap<>();
- List:表示该列表只能存储String类型的数据。
- Map<String, Integer>:表示该映射的键为String类型,值为Integer类型。
- 方法中的泛型
public <T> void printArray(T[] array) {
for (T element : array) {
System.out.println(element);
}
}
这里的表示方法是泛型的,T可以是任何类型。
使用泛型的好处
- 类型安全:
在编译时检查类型,避免了运行时的ClassCastException。
List<String> list = new ArrayList<>();
list.add("Hello");
// list.add(123); // 编译时会报错
- 避免强制类型转换:
使用泛型后,无需进行类型转换,因为在编译时类型已经确定。
List<String> list = new ArrayList<>();
list.add("Hello");
String str = list.get(0); // 不需要强制转换
- 代码重用:
泛型允许编写与类型无关的代码,提升了代码的重用性。
队列的声明和实例化
语法格式
接口/实现类<元素类型> 变量名 = new 实现类<>();
- 接口/实现类:表示对象的数据结构
- <元素类型>:这是一个泛型参数,表示队列中存储的元素类型。泛型提供了类型安全,确保队列中只能存储该类型的对象
- 变量名:用于引用
接口类型<元素类型>
类型的实例。你可以选择任何合法的变量名 - new:关键字,用于创建对象的实例
- 实现类<>:具体的实现类
- <>:表示类型推断。Java编译器可以根据左侧的变量声明自动推断出泛型类型。
例如:
Queue<TreeNode> deque = new ArrayDeque<>();
声明了一个类型为Queue<TreeNode>
的变量deque
,并将其初始化为一个ArrayDeque<TreeNode>
的新实例。
变量声明:接口 vs 具体实现类
方法一:使用接口
Deque<Integer> deque = new ArrayDeque<>();
方法二:直接使用具体实现类,在变量声明时就明确数据结构的具体实现
ArrayDeque<TreeNode> deque = new ArrayDeque<>();
//适用于需要特定于ArrayDeque的方法和特性的场景。
- 方法一:使用接口的定义方式只能访问Queue接口中定义的方法。这种方式确保了使用的是标准的队列操作。例如,可以使用add(), remove(), peek(), poll()等方法,但不能使用ArrayDeque特有的方法。
- 方法二:这里直接使用了具体实现类,能访问ArrayDeque的所有方法,如addFirst(), addLast(), removeFirst(), removeLast()等方法,这些方法在Queue接口中没有定义。如果需要更换实现类,左侧的声明也需要修改。
总结:
- 使用Queue接口声明变量(如Queue deque),可以提高代码的灵活性和可维护性。
- 使用具体的ArrayDeque类声明变量(如ArrayDeque deque),可以访问ArrayDeque特有的方法,但限制了灵活性。
详细应用场景
接口
List
:普通列表。Queue
:队列,适用于需要队列特性(如FIFO操作)的场景(如BFS)Deque
:双端队列,适用于需要双向队列特性(如从两端插入和删除元素)的场景
实现类
LinkedList
:基于链表的双向队列,支持快速的插入和删除操作。ArrayList
:基于动态数组的列表,支持快速随机访问元素,但在插入和删除操作时性能可能较差(特别是在列表中间)。ArrayDeque
:基于数组的双向队列,因为它不需要维护链表结构,所以提供了比LinkedList更高效的元素随机访问和插入、删除操作。
总结
序号 | 接口 | 声明创建方式 | 适用场景 |
---|---|---|---|
1 | Deque | Deque deque = new LinkedList<>(); | 需要频繁在队列头部和尾部进行插入和删除操作。 |
2 | Deque | Deque deque = new ArrayDeque<>(); | 需要快速访问元素、插入和删除操作,但不需要线程安全。 |
3 | Queue | Queue deque = new LinkedList<>(); | 需要队列特性的场景,例如广度优先搜索BFS。 |
4 | Queue | Queue deque = new ArrayDeque<>(); | 需要高效的队列操作,但不需要线程安全。 |
5 | List | List result = new LinkedList<>(); | 需要频繁进行插入、删除操作。 |
6 | List | List result = new ArrayList<>(); | 需要频繁随机访问元素。 |
以上的定义方式是面向接口编程的一种体现,使用接口类型声明变量,再使用具体的实现类来实例化对象。这种方式的好处是提高了代码的灵活性和可维护性,因为我们可以轻松更改实现类(例如,用LinkedList代替ArrayDeque)而不需要修改其他代码。