一、集合复习(主要对底层原理进行初步的学习)
1.架构体系
总结:集合主要分为两大系列:Collection和Map,Collection 表示一组对象,Map表示一组映射关系或键值对。
2.Collection
常用方法:
public void collection(){
ArrayList list = new ArrayList<>();
//add:添加单个元素
list.add("孙悟空");
list.add("唐僧");
list.add("猪八戒");
System.out.println(list);
//remove:删除指定元素
//删除指定下标
//list.remove(0);
//删除指定元素
list.remove("孙悟空");
System.out.println(list);
//contains:查找元素是否存在
System.out.println(list.contains("孙悟空"));
System.out.println(list.contains("猪八戒"));
//size:获取元素个数
System.out.println(list.size());
//isEmpty:判断是否为空
System.out.println(list.isEmpty());
//clear:清空
list.clear();
System.out.println(list);
//addAll:添加多个元素
ArrayList list2 = new ArrayList();
list2.add("亚索");
list2.add("剑圣");
list.addAll(list2);
System.out.println(list2);
//containsAll:查找多个元素是否都存在
System.out.println(list.containsAll(list2));
//removeAll:删除多个元素
list.removeAll(list2);
System.out.println(list);
//说明:以 ArrayList 实现
}
输出结果:
遍历方式:
迭代器:
public class Iterator {
public static void main(String[] args) {
Collection col = new ArrayList();
col.add(new Book("三国演义", "罗贯中", 10.1));
col.add(new Book("小李飞刀", "古龙", 5.1));
col.add(new Book("红楼梦", "曹雪芹", 34.6));
//System.out.println("col=" + col);
//现在老师希望能够遍历 col 集合
//1. 先得到 col 对应的 迭代器
java.util.Iterator iterator = col.iterator( );
//2. 使用 while 循环遍历( 快捷键 itit:直接召唤出while 也可以使用 ctrl+j 键查看快捷键)
while (iterator.hasNext()) { //查看下一个元素是否为空 如果为空则退出程序
Object obj = iterator.next();
System.out.println("obj=" + obj);
}
//3.当退出 while 循环后 , 这时 iterator 迭代器,指向最后的元素
// System.out.println(iterator.next());
//4. 如果希望再次遍历,需要重置我们的迭代器
iterator = col.iterator();
while (iterator.hasNext()) {
Object obj = iterator.next();
System.out.println("obj1="+obj);
}
}
}
class Book{
private String name;
private String author;
private double price;
public Book(String name, String author, double price) {
this.name = name;
this.author = author;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
'}';
}
}
输出结果:
加强for循环:
public static void main(String[] args) {
Collection col = new ArrayList();
col.add(new Book("三国演义", "罗贯中", 10.1));
col.add(new Book("小李飞刀", "古龙", 5.1));
col.add(new Book("红楼梦", "曹雪芹", 34.6));
//解读:
/**
* 1.使用增强for,在collection集合
* 2.增强for,底层仍然是迭代器
* 3.增强for可以理解为简化版本的 迭代器遍历
* 4.迭代器的快捷键 I
*/
for (Object obj:col){
System.out.println(obj);
}
}
输出结果:
List集合与Set集合(不做详解,可以去看b站韩顺平老师):
2.Map集合:
二、数据结构和算法(开始初步学习)
1.线性结构和非线性结构
2.稀疏数组和队列
稀疏数组;
基本介绍:
代码实现:
package com.tit.sparseArray;
/**
* @author peiyu
* @version 1.0
*/
public class SparseArray {
public static void main(String[] args) {
//创建一个原始的二维数组 11 * 11
//0:表示没有棋子 1:表示黑棋 2:表示蓝棋
int chessArr1[][] = new int[11][11];
chessArr1[1][2]=1;
chessArr1[2][3]=2;
chessArr1[3][4]=2;
System.out.println("===========原始二维数组===========");
for (int[] row : chessArr1){
for (int data : row){
System.out.printf("%d\t",data);
}
System.out.println();
}
//将二维数组转换成稀疏数组
//1.先遍历二维数组 得到非零的个数
int sum = 0;
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if (chessArr1[i][j] != 0){
sum++;
}
}
}
//2.创建稀疏数组
int sparseArr[][] = new int[sum+1][3];
sparseArr[0][0] = 11;
sparseArr[0][1] = 11;
sparseArr[0][2] = sum;
//遍历原数组 找到非零的元素
int count = 0; //用来记录稀疏数组第几行 当遇到非零是++
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if (chessArr1[i][j] != 0){
count++;
sparseArr[count][0] = i;
sparseArr[count][1] = j;
sparseArr[count][2] = chessArr1[i][j];
}
}
}
//输出稀疏数组
System.out.println("===========稀疏数组=========");
for (int[] row : sparseArr){
for (int data : row){
System.out.printf("%d\t",data);
}
System.out.println();
}
//将稀疏数组转换成二维数组
/**
* 1. 先读取第一行的数据 稀疏数组的第一行用来存放原二维数组的行列个数
* 2. 读取其他行 行内容 第一个元素第第几行 第二个元素第几列 第三个元素是存放的值
*/
//1.先创建一个新的数组
int chessArr2[][] = new int[sparseArr[0][0]][sparseArr[0][1]];
//2.读取稀疏数组的其他行 将值赋给原数组
for (int i = 1; i < sparseArr.length; i++) {
chessArr2[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
}
//输出新数组
System.out.println("=======新数组=======");
for (int[] row : chessArr2){
for (int data : row){
System.out.printf("%d\t",data);
}
System.out.println();
}
}
}
输出结果:
队列:
介绍;
数组模拟队列:
public class ArrayQueueDemo {
public static void main(String[] args) {
//创建一个队列长度是3
ArrayQueue queue = new ArrayQueue(3);
//接受用户输入
char key = ' ';
Scanner sc = new Scanner(System.in);
boolean loop = true;
while (loop){
System.out.println("s(show):显示队列");
System.out.println("e(exit):退出");
System.out.println("a(add):添加数据到队列");
System.out.println("g(get):从队列取出数据");
System.out.println("h(head):查看对列头部数据");
key = sc.next().charAt(0);//接收一个字符
switch (key){
case 's' :
try {
queue.showQueue();
}catch (Exception e){
System.out.println(e.getMessage());
};
break;
case 'a' :
System.out.println("输入一个数字");
int value = sc.nextInt();
queue.addQueue(value);
break;
case 'g' :
try {
int queue1 = queue.getQueue();
System.out.printf("取出数据是%d\n",queue1);
}catch (Exception e){
System.out.println(e.getMessage());
};
break;
case 'h' :
try {
int res = queue.headQueue();
System.out.printf("头部数据是%d\n",res);
}catch (Exception e){
System.out.println(e.getMessage());
};
break;
case 'e' :
sc.close();
loop = false;
break;
}
}
System.out.println("退出系统");
}
}
//使用数组模拟队列,先编写一个ArrayQueue类
class ArrayQueue{
private int maxSize; //表示数组的长度
private int front;//队列头
private int rear;//队列尾
private int[] arr; //数据存放的数组,用来模拟队列
public ArrayQueue(int arrMaxSize) {
maxSize = arrMaxSize;
arr = new int[maxSize];
front = -1; //队列头 默认是-1 判断出front是指向队列头部的前一个位置 队列是先进后出 所以对头是0的前一个
rear = -1; //队列尾 默认是-1 指向队里尾部最后一个元素
}
//判断队列是否满了
public boolean isFull(){
return rear == maxSize - 1;
}
//判断对垒是否为空
public boolean isEmpty(){
return front == rear;
}
//添加数组到队列
public void addQueue(int n){
//先判断队列是否满了
if (isFull()){
System.out.println("队列已满");
return;
}
rear++;
arr[rear] = n;
}
//获取队列的数据,出队列
public int getQueue(){
//先判断队列是否为空
if (isEmpty()){
throw new RuntimeException("队列已空");
}
//队列先进后出 从头部开始出数据
front++;
return arr[front];
}
//显示队列的所以数据
public void showQueue(){
//先判断队列是否为空
if (isEmpty()){
throw new RuntimeException("队列已空");
}
for (int i = 0; i < arr.length; i++) {
System.out.printf("arr[%d]=%d\n",i,arr[i]);
}
}
//显示队列头部的数据,不取出
public int headQueue(){
//先判断队列是否为空
if (isEmpty()){
throw new RuntimeException("队列已空");
}
return arr[front+1];
}
}
数组模拟环形队列:
public class CircleArrayQueueDemo {
public static void main(String[] args) {
// 队列长度为3 因为在创建环形的 (read+1)%maxsize = front; 导致其会缺少一个
CircleArray queue = new CircleArray(4);
//接受用户输入
char key = ' ';
Scanner sc = new Scanner(System.in);
boolean loop = true;
while (loop){
System.out.println("s(show):显示队列");
System.out.println("e(exit):退出");
System.out.println("a(add):添加数据到队列");
System.out.println("g(get):从队列取出数据");
System.out.println("h(head):查看对列头部数据");
key = sc.next().charAt(0);//接收一个字符
switch (key){
case 's' :
try {
queue.showQueue();
}catch (Exception e){
System.out.println(e.getMessage());
};
break;
case 'a' :
System.out.println("输入一个数字");
int value = sc.nextInt();
queue.addQueue(value);
break;
case 'g' :
try {
int queue1 = queue.getQueue();
System.out.printf("取出数据是%d\n",queue1);
}catch (Exception e){
System.out.println(e.getMessage());
};
break;
case 'h' :
try {
int res = queue.headQueue();
System.out.printf("头部数据是%d\n",res);
}catch (Exception e){
System.out.println(e.getMessage());
};
break;
case 'e' :
sc.close();
loop = false;
break;
}
}
System.out.println("退出系统");
}
}
class CircleArray{
private int maxSize; //表示数组的长度
//front 变量的含义做一个调整: front 就指向队列的第一个元素, 也就是说 arr[front] 就是队列的第一个元素
//front 的初始值 = 0
private int front;
//rear 变量的含义做一个调整:rear 指向队列的最后一个元素的后一个位置. 因为希望空出一个空间做为约定.
//rear 的初始值 = 0
private int rear;//队列尾
private int[] arr; //数据存放的数组,用来模拟队列
public CircleArray(int arrMaxSize) {
maxSize = arrMaxSize;
arr = new int[maxSize];
}
//判断队列是否满了
public boolean isFull(){
return (rear + 1) % maxSize == front;
}
//判断对垒是否为空
public boolean isEmpty(){
return front == rear;
}
//添加数组到队列
public void addQueue(int n){
//先判断队列是否满了
if (isFull()){
System.out.println("队列已满");
return;
}
arr[rear] = n;
rear = (rear + 1) % maxSize;
}
//获取队列的数据,出队列
public int getQueue(){
//先判断队列是否为空
if (isEmpty()){
throw new RuntimeException("队列已空");
}
//队列先进后出 从头部开始出数据
int n = arr[front]; //为什么要先取出值呢 因为接下来需要将front的值变换
front = (front + 1) % maxSize;
return n;
}
//显示队列的所有数据
public void showQueue(){
//先判断队列是否为空
if (isEmpty()){
throw new RuntimeException("队列已空");
}
for (int i = front ; i < front +size(); i++) {
System.out.printf("arr[%d]=%d\n",i % maxSize,arr[i % maxSize]);
}
}
public int size(){
//rear = 2
//front = 1
//maxSize = 3
return (rear + maxSize - front) % maxSize;
}
//显示队列头部的数据,不取出
public int headQueue(){
//先判断队列是否为空
if (isEmpty()){
throw new RuntimeException("队列已空");
}
return arr[front];
}
}
链表(单链表):
代码实现:
public class SingleLinkedListDemo {
public static void main(String[] args) {
//测试
HeroNode heroNode = new HeroNode(1,"宋江","狗杂种");
HeroNode heroNode2 = new HeroNode(2,"林冲","豹子头");
HeroNode heroNode3 = new HeroNode(3,"吴用","狗腿子");
HeroNode heroNode4 = new HeroNode(4,"李逵","大二愣子");
HeroNode heroNode5 = new HeroNode(4,"李鬼","小黑子");
HeroNode heroNode6 = new HeroNode(5,"李鬼","小黑子");
//将上面的元素添加到链表中
SingleLinkedList singleLinkedList = new SingleLinkedList();
// singleLinkedList.add(heroNode);
// singleLinkedList.add(heroNode3);
// singleLinkedList.add(heroNode2);
// singleLinkedList.add(heroNode4);
singleLinkedList.addByOrder(heroNode);
singleLinkedList.addByOrder(heroNode3);
singleLinkedList.addByOrder(heroNode2);
singleLinkedList.addByOrder(heroNode4);
singleLinkedList.addByOrder(heroNode4);
//遍历
singleLinkedList.list();
singleLinkedList.update(heroNode5);
System.out.println("============修改后的内容============");
singleLinkedList.list();
singleLinkedList.del(4);
singleLinkedList.del(1);
System.out.println("============删除后的内容============");
singleLinkedList.list();
}
}
class SingleLinkedList{
//先初始化一个头节点,头节点不能动,不存放任何数据
HeroNode head = new HeroNode(0,"","");
public void add(HeroNode heroNode){
//因为头节不能动 所以我们使用一个 tmp 中间节点来做完 head 节点的替代
HeroNode temp = head;
//遍历链表找到最后
while (true){
if (temp.next == null){
//找到链表最后
break;
}
temp = temp.next;
}
//当退出 while 循环时,temp就指向了链表的最后一个
//将最后一个的next添加 新元素
temp.next = heroNode;
}
//显示链表
public void list(){
//判断是否为空
if (head.next == null){
System.out.println("链表为空");
return;
}
//同上 head指针不能动 所以创一个中间变量
HeroNode temp = head;
while (true){
//判断链表是否为空
if (temp.next == null){
break;
}
//将temp后移
temp = temp.next;
System.out.println(temp);
}
}
//修改方法
/**
* 修改节点的信息,根据 no 编号来进行修改,即 no 编号不能改
* 说明:1.根据 newHeroNode 的 no 来修改即可
* @param newHeroNode
*/
public void update(HeroNode newHeroNode){
//判断是否为空
if (head.next == null){
System.out.println("链表为空");
}
//定义辅助变量
HeroNode temp = head;
boolean flag = false; //表示是否找到修改的节点
while (true){
if (temp == null){
break; //已经遍历完链表
}else if (temp.no == newHeroNode.no){
//找到
flag = true;
break;
}
temp = temp.next;
}
//根据 flag 判断是否找到要修改的节点
if (flag){
temp.name = newHeroNode.name;;
temp.nickName = newHeroNode.nickName;
} else {
System.out.printf("没有找到 编号为 %d 的节点,不能修改\n",newHeroNode.no);
}
}
//链表删除
/**
* 思路:1.head不能动,因此需要创建一个 temp 辅助节点找到待删除节点的前一个节点
* 2.说明我们在比较时,是 temp.next.on 和 需要删除的 no 做比较
* @param no
*/
public void del(int no){
HeroNode temp = head;
boolean flag = false; //标记是否需要删除
while (true){
if (temp.next == null){
break;
} else if (temp.next.no == no){
//找到待删除节点的前一个
flag = true;
break;
}
temp = temp.next;
}
if (flag){
// 可以删除
temp.next = temp.next.next;
} else {
System.out.printf("找不到编号为 %n 的英雄",no);
}
}
//第二种方式添加英雄时,根据排名将英雄插入到指定位置 (如果有这个排名,则添加失败,并给出提示)
public void addByOrder(HeroNode heroNode){
//因为头节点不能动,所以创建一个辅助指针(变量)来帮助找到添加的位置
//因为单链表,因为我们找到的temp是位于添加位置的前一个节点,否则无法插入
HeroNode temp = head;
boolean flag = false; //flag 标示添加的编号是否存在,默认是false
while (true){
if (temp.next == null){ //说明 temp 已经是链表的最后了
break;
} else if (temp.next.no > heroNode.no){ //位置找到了,就在 temp 后面
break;
} else if (temp.next.no == heroNode.no){//说明希望添加的 heroNode 编号已经存在
flag = true; //编号存在
break;
}
temp = temp.next;
}
//判断 flag 的值
if (flag){ //不能添加,说明编号已经存在
System.out.printf("准备出入的英雄编号 %d 已经存在了,不能加入\n",heroNode.no);
}else {
//插到 temp 的后面
heroNode.next = temp.next;
temp.next = heroNode;
}
}
}
class HeroNode{
public int no;
public String name;
public String nickName;
public HeroNode next;
public HeroNode(int no, String name, String nickName) {
this.no = no;
this.name = name;
this.nickName = nickName;
}
@Override
public String toString() {
return "\n HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
", nickName='" + nickName + '\'' +
'}';
}
}