1. Java 集合框架
Java 集合框架 Java Collection Framework ,又被称为容器 container ,是定义在 java.util 包下的一组接口 interfaces 和其实现类 classes 。
其主要表现为将多个元素 element 置于一个单元中,用于对这些元素进行快速、便捷的存储 store 、检索
retrieve 、管理 manipulate ,即平时我们俗称的增删查改 CRUD 。
2. Collection常用方法
方法 | 说明 |
---|---|
boolean add(E e) | 将元素e放入集合中 |
void clear() | 删除集合中的所有元素 |
boolean isEmpty() | 判断集合是否为空集合 |
boolean remove(Object e) | 如果元素e出现在集合中,删除第一个出现的元素e |
int size() | 返回集合中的元素个数 |
Object[] toArray() | 返回一个装有所有集合中元素的数组 |
代码示例:
import java.util.Collection;
import java.util.ArrayList;
import java.util.Arrays;
public class Test{
public static void main(String [] args){
Collection<String> list = new ArrayList<>();
//输出集合大小
System.out.println(list.size());// 0
//判断集合是否为空
System.out.println(list.isEmpty);// true
//在集合中放入 我 爱 Java
list.add("我");
list.add("爱");
list.add("Java");
//输出集合大小
System.out.println(list.size());//3
//判断集合是否为空
System.out.println(list.isEmpty());//false
//返回一个装有所有集合元素的数组
Object[] array = list.toArray();
//将这个数组以字符串的形式打印
System.out.println(Arrays.toString(array));//[我,爱,Java]
//遍历list
for(String s : list){
System.out.println(s);
//输出结果
//我
//爱
//Java
}
//删除 "爱"
list.remove("爱");
//遍历list
for(String s : list){
System.out.println(s);
//输出结果
//我
//Java
}
//删除顺序表中所有的元素
list.clear();
System.out.println(list.size());//0
System.out.println(list.isEmpty);//true
}
}
3. 初识泛型
3.1 泛型的分类
- 泛型类
- 泛型方法
3.2 泛型类的定义的简单演示
// 1. 尖括号 <> 是泛型的标志
// 2. E 是类型变量(Type Variable),变量名一般要大写
// 3. E 在定义时是形参,代表的意思是 MyArrayList 最终传入的类型,但现在还不知道
public class MyArrayList<E> {
private E[] array;
private int size;
...
}
注意: 泛型类可以一次有多个类型变量,用逗号分割
3.3 泛型的意义
在存储元素的时候,可以自动进行类型检查
在获取元素的时候,可以自动进行类型转换
3.4 泛型类的使用
// 定义了一个元素是 Book 引用的 MyArrayList
MyArrayList<Book> books = new MyArrayList<Book>();
books.add(new Book());
// 会产生编译错误,Person 类型无法转换为 Book 类型
books.add(new Person());
// 不需要做类型转换
Book book = book.get(0);
// 不需要做类型转换
// 会产生编译错误,Book 类型无法转换为 Person 类型
Person person = book.get(0);
通过以上代码,我们可以看到泛型类的一个使用方式:只需要在所有类型后边跟尖括号,并且尖括号内是真正的类型,即 E 可以看作的最后的类型。
注意: Book 只能想象成 E 的类型,但实际上 E 的类型还是 Object。
泛型只在编译过程中起作用,在运行的时候是没有泛型的概念的
3.5 泛型的总结
- 泛型是为了解决某些容器、算法等代码的通用性而引入,并且能在编译期间做类型检查。
- 泛型利用的是 Object 是所有类的祖先类,并且父类的引用可以指向子类对象的特定而工作。
- 泛型是一种编译期间的机制,即 MyArrayList 和 MyArrayList 在运行期间是一个类型。
- 泛型是 java 中的一种合法语法,标志就是尖括号 <>
4. 初始包装类
Object 引用可以指向任意类型的对象,但有例外出现了,8 种基本数据类型不是对象,那岂不是刚才的泛型机制要失效了?
为了解决这个问题,java 引入了一类特殊的类,即这 8 种基本数据类型的包装类,在使用过程中,会将类似 int 这样的值包装到一个对象中去。
4.1 基本数据类型和包装类直接的对应关系
基本数据类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
基本就是类型的首字母大写,除了 Integer 和 Character。
4.2 包装类的使用,装箱和拆箱
int a = 10;
Integer a1 = a;//自动装箱\装包
Integer a2 = Integer.valueOf(a);//手动装箱\装包
//
Integer a = 10;
int a1 = a;//自动拆箱\自动拆包
int a2 = a.intValue();//手动拆箱\手动拆包
注意事项
Integer a = 100;
Integer b = 100;
System.out.println(a==b); //true
Integer a1 = 200;
Integer b1 = 200;
System.out.println(a1==a2);//false
//包装类是引用类型,a和b是一个引用,存的是对象的地址
//用等号判断相等是判断他们两个的地址是否相等
//-128 -> 127 在一个缓存数组中, 其他范围需要新new一个对象 开辟空间
//-128 -> 127 为true 其他范围为false
5. List 的使用
5.1 常见方法
5.1.1 List(线性表)
方法 | 解释 |
---|---|
boolean add(E e) | 尾插e |
void add(int index,E element) | 将e插入到index的位置 |
boolean addAll(Collection<?extends E> c) | 尾插c中的元素 |
E remove(int index) | 删除index位置的元素 |
boolean remove (Object o ) | 删除遇到的第一个o |
E get(int index) | 获取下标index位置的元素 |
Eset (int index,E element) | 将下标index位置的元素设置为element |
void clear() | 清空 |
boolean contains(Object o ) | 判断o是否在线性表中 |
int indexOf(Object o) | 返回第一个o所在的下标 |
int lastIndexOf(Object o ) | 返回最后一个o所在的下标 |
ListsubList(int fromIndex,int toIndex) | 截取部分list |
5.1.2 ArrayList(顺序表)
方法 | 解释 |
---|---|
ArrayList() | 无参构造 |
ArrayList(Collection<?extends E>c) | 利用其他Collection构建ArrayList |
ArrayList(int initialCapacity) | 指定顺序表的初始容量 |
5.1.3 LinkedList(链表)
方法 | 解释 |
---|---|
LinkedList() | 无参构造 |
5.2 示例
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
public class ListDemo{
public static void main(String [] args){
List<String> courese = new ArrayList<>();
courses.add("C语言");
courses.add("Java SE");
courses.add("Java Web");
courses.add("Java EE");
// 和数组一样,允许添加重复元素
courses.add("C语言");
// 按照添加顺序打印
System.out.println(courses);
//执行结果[C 语言, Java SE, Java Web, Java EE, C 语言]
// 类似数组下标的方式访问
System.out.println(courses.get(0));
//执行结果 C语言
System.out.println(courses);
//[C 语言, Java SE, Java Web, Java EE, C 语言]
courses.set(0, "计算机基础");
//set 会将原来的元素覆盖
System.out.println(courses);
//[计算机基础, Java SE, Java Web, Java EE, C 语言]
// 截取部分 [1, 3)
List<String> subCourses = courses.subList(1, 3);
System.out.println(subCourses);
//[Java SE, Java Web] 截取是左闭右开的,截取并不是截取出来一个新的数组,而是在原来的基础上输出截取范围的元素
subCourses.set(0,"小说");
//将截取出来的数组,0下标的元素改为小说
System.out.println(subCourses);
//[小说,Java Web]
System.out.println(courses);
//[计算机基础, 小说, Java Web, Java EE, C 语言]
// 重新构造
List<String> courses2 = new ArrayList<>(courses);
System.out.println(courses2);
//[计算机基础, 小说, Java Web, Java EE, C 语言]
List<String> courses3 = new LinkedList<>(courses);
System.out.println(courses3);
//[计算机基础, 小说, Java Web, Java EE, C 语言]
// 引用的转换
ArrayList<String> courses4 = (ArrayList<String>)courses2;
System.out.println(courses4);
//[计算机基础, 小说, Java Web, Java EE, C 语言]
// LinkedList<String> c = (LinkedList<String>)course2; 错误的类型
LinkedList<String> courses5 = (LinkedList<String>)courses3;
System.out.println(courses5);
//[计算机基础, 小说, Java Web, Java EE, C 语言]
// ArrayList<String> c = (ArrayList<String>)course3; 错误的类型
}
}
6. 栈
6.1 栈的概念
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一段称为栈顶,另一端称为栈底。栈中的元素蹲守后进先出原则
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶
出栈:栈的删除操作叫做出栈,出数据在栈顶
6.2 常见方法
方法 | 解释 |
---|---|
E push(E item) | 压栈 |
E pop() | 出栈 |
E peek() | 查看栈顶元素但不删除 |
boolean empty() | 判断栈是否为空 |
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
stack.push(1);
stack.push(2);
stack.push(3);
int tmp = stack.peek();//查看栈顶元素 用tmp接收
System.out.println(tmp);
int ret = stack.pop();//出栈顶元素 3
System.out.println(ret);//输出要出栈的元素
System.out.println(stack);//输出栈中元素
stack.pop();//出栈顶元素 2
stack.pop();//出栈顶元素 1
boolean flg =stack.empty();//判断栈是否为空,用flg接收
System.out.println(flg);
}
//输出结果
3
3
[1, 2]
true
7. 队列(Queue)
7.1 概念
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO。 入队列:进行插入操作的一端称为队尾 ,出队列:进行删除操作的一端称为队头
7.2 用单链表实现队列
package Queue;
class Node{
private int val;
private Node next;
public int getVal() {
return val;
}
public void setVal(int val) {
this.val = val;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
public Node(int val) {
this.val = val;
}
}
public class MyQueue {
private Node first;
private Node last;
//入队
public void offer(int val){
Node node = new Node(val);
if(first == null ){
this.first = node;
this.last = node;
}else{
this.last.setNext(node);
this.last = node;
}
}
//出队
public int poll(){
if(isEmpty()){
throw new NullPointerException("队列为空");
}else{
int ret = this.first.getVal();
this.first = this.first.getNext();
return ret;
}
}
//得到队头元素 但是不会删除
public int peek(){
if(isEmpty()){
throw new NullPointerException("队列为空");
}else{
return this.first.getVal();
}
}
//判断队列是否为空
public boolean isEmpty(){
return this.first == null;
}
}
7.3 循环队列
7.4 双端队列(Deque)
双端队列(deque)是指允许两端都可以进行入队和出队操作的队列,deque 是 “double ended queue” 的简称。那就说明元素可以从队头出队和入队,也可以从队尾出队和入队
7.5 Queue 的错误处理
错误处理 | 抛出异常 | 返回特殊值 |
---|---|---|
入队列 | add(e) | offer(e) |
出队列 | remove() | poll() |
队首元素 | element() | peek() |
7.6 Deque的错误处理
头部/尾部 | 头部元素 | 头部元素 | 尾部元素 | 尾部元素 |
---|---|---|---|---|
错误处理 | 抛出异常 | 返回特殊值 | 抛出异常 | 返回特殊值 |
入队列 | addFirst(e) | offerFirst(e) | addLast(e) | offerLast(e) |
出队列 | removeFirst() | pollFirst() | removaLast() | pollLast() |
获取元素 | getFirst() | peekLast() | getLast() | peekLast() |