Commit on 2025/03/26 周三 18:16:04.26

This commit is contained in:
zhangsan 2025-03-26 18:16:04 +08:00
parent 24e284ace3
commit 34e53e1a72
4 changed files with 714 additions and 463 deletions

File diff suppressed because it is too large Load Diff

View File

@ -81,13 +81,13 @@ IDEA快捷键
2. 在 `System.out.println()` 方法中,"ln" 代表 "line",表示换行。因此,`println` 实际上是 "print line" 的缩写。这个方法会在输出文本后自动换行.
```text
```java
System.out.println("nihao "+1.3331) #Java 会自动将数值转换为字符串
```
当直接打印一个没有重写 `toString()` 方法的对象时Java 默认会调用 `Object` 类的 `toString()` 方法,其输出格式通常为:
```text
```java
java.lang.Object@15db9742
```
@ -95,7 +95,7 @@ IDEA快捷键
当打印重写`toString()` 方法的对象时:
```text
```java
class Person {
private String name;
private int age;
@ -120,7 +120,7 @@ IDEA快捷键
```
```text
```java
Person{name='Alice', age=30}
```
@ -128,7 +128,7 @@ IDEA快捷键
3. 一维数组创建:
```text
```java
// 方式1先声明再指定长度默认值为0、null等
int[] arr1 = new int[10]; // 创建一个长度为10的int数组
@ -139,14 +139,13 @@ IDEA快捷键
// 方式3结合new关键字和初始化列表创建数组常用于明确指定类型时
int[] arr3 = new int[]{1, 2, 3, 4, 5}; // 与方式2效果相同
```
4. 字符串创建
```text
```java
String str = "Hello, World!"; //1直接赋值
String str = new String("Hello, World!"); //使用 new 关键字
@ -157,6 +156,70 @@ IDEA快捷键
#### Java传参方式
基本数据类型Primitives
- 传递方式:按值传递
每次传递的是变量的值的副本,对该值的修改不会影响原变量。例如:`int``double``boolean` 等类型。
引用类型(对象)
- 传递方式:对象引用的副本传递
传递的是对象引用的一个副本指向同一块内存区域。因此方法内部通过该引用修改对象的状态会影响到原对象。如数组、集合、String、以及其他所有对象类型。
**浅拷贝**
拷贝对象本身,但内部成员(例如集合中的元素)只是复制引用,新旧对象的内部成员指向同一份内存。如果内部元素是不可变的(如 Integer、String 等),这种拷贝通常足够。如果元素是可变对象,修改其中一个对象**可能会影响**另一个。
```java
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
// 浅拷贝:新列表中的元素引用和原列表中的是同一份
List<Integer> shallowCopy = new ArrayList<>(list);
```
可变对象,浅拷贝修改对象会出错!
```java
List<Box> list = new ArrayList<>();
list.add(new Box(1));
list.add(new Box(2));
list.add(new Box(3));
List<Box> shallowCopy = new ArrayList<>(list);
shallowCopy.get(0).value = 10; // 修改 shallowCopy 中第一个 Box 的 value
System.out.println(list); // 输出: [10, 2, 3],因为同一 Box 对象被修改
System.out.println(shallowCopy); // 输出: [10, 2, 3]
```
**深拷贝**
不仅复制对象本身,还递归地复制其所有内部成员,从而生成一个完全独立的副本。即使内部元素是可变的,修改新对象也不会影响原始对象。
```java
// 深拷贝 List<MyObject> 的例子
List<MyObject> originalList = new ArrayList<>();
originalList.add(new MyObject(10));
originalList.add(new MyObject(20));
List<MyObject> deepCopy = new ArrayList<>();
for (MyObject obj : originalList) {
deepCopy.add(new MyObject(obj)); // 每个元素都创建一个新的对象
}
```
#### 日期
在Java中
@ -196,7 +259,7 @@ LocalDateTime.now(),获取当前时间
```text
```java
// 文件com/example/PrivateExample.java
package com.example;
@ -215,7 +278,7 @@ public class PrivateExample {
修饰符不仅可以用来修饰成员变量和方法,也可以用来**修饰类**。顶级类只能使用 `public` 或默认(即不写任何修饰符,称为包访问权限)。内部类可以使用所有访问修饰符(`public``protected``private` 和默认),这使得你可以更灵活地控制嵌套类的访问范围。
```text
```java
public class OuterClass {
// 内部类使用private只能在OuterClass内部访问
private class InnerPrivateClass {
@ -258,7 +321,7 @@ public class OuterClass {
用途:适用于内部类与外部类关系密切,需要频繁访问外部类成员的情况。
```text
```java
public class OuterClass {
class InnerClass implements Runnable {
// static int count = 0; // 编译错误
@ -294,7 +357,7 @@ public class OuterClass {
用途:适用于只在方法或代码块中使用的类,有助于将实现细节隐藏在方法内部。
```text
```java
public class OuterClass {
public void startThread() {
class LocalInnerClass implements Runnable {
@ -327,7 +390,7 @@ public class OuterClass {
用途:适合当内部类工作不依赖外部类实例时使用,常用于实现与外部类关系不那么密切的帮助类。
```text
```java
public class OuterClass {
// 外部类的静态成员
private static int staticVar = 10;
@ -371,7 +434,7 @@ public class OuterClass {
用途:适用于创建一次性使用的实例,通常用于接口或抽象类的实现。
```text
```java
//eg1
public class OuterClass {
public static void main(String[] args) {
@ -413,7 +476,7 @@ public class GUIApp {
1. 创建`ActionListener`实例
```text
```java
new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Button was clicked!");
@ -432,7 +495,7 @@ new ActionListener() {
2. 将匿名内部类添加为事件监听器
```text
```java
button.addActionListener(...);
```
@ -446,7 +509,7 @@ Lambda表达式特别适用于**只有单一抽象方法**的接口(也即**
**`@FunctionalInterface` 注解**:这是一个可选的注解,用于表示接口是一个函数式接口。虽然不是强制的,但它可以帮助编译器识别意图,并检查接口是否确实只有一个抽象方法。
```text
```java
public class LambdaExample {
// 定义函数式接口doSomething 有两个参数
@FunctionalInterface
@ -479,7 +542,7 @@ public class LambdaExample {
可选的大括号:如果主体只有一个语句,可以不使用大括号。
可选的返回关键字如果主体只有一个表达式返回值则编译器会自动返回值使用大括号需显示retrun如果函数是void则不需要返回值。
```text
```java
// 定义一个函数式接口
interface Calculator {
int add(int a, int b);
@ -507,7 +570,7 @@ public class LambdaReturnExample {
`list.forEach`这个方法接受一个**函数式接口**作为参数。它只有一个抽象方法 `accept(T t)`因此,可以使用 lambda 表达式来**实现**。
```text
```java
import java.util.Arrays;
import java.util.List;
@ -536,7 +599,7 @@ public class Main {
如果返回正数,则 `a` 应该排在 `b` 的后面。
```text
```java
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@ -564,7 +627,7 @@ public class Main {
**1.静态初始化块Static Initialization Block**
```text
```java
public class MyClass {
static int num1, num2;
@ -590,7 +653,7 @@ public class MyClass {
输出:
```text
```java
静态代码块1执行
静态代码块2执行
main方法执行
@ -603,7 +666,7 @@ main方法执行
**2.在声明时直接初始化**
```text
```java
public class MyClass {
// 直接在声明时初始化静态成员变量
public static int staticVariable = 42;
@ -614,7 +677,7 @@ public class MyClass {
静态成员变量的访问不需要创建 `MyClass` 的实例,可以直接通过类名访问:
```text
```java
int value = MyClass.staticVariable;
MyClass obj = new MyClass();
System.out.println("obj.num1 = " + obj.staticVariable); #通过示例访问也可以
@ -638,7 +701,7 @@ System.out.println("obj.num1 = " + obj.staticVariable); #通过示例访问也
- 非静态成员变量。
- 非静态方法(必须通过对象实例访问)。
```text
```java
public class MyClass {
private static int staticVar = 10;
private int instanceVar = 20;
@ -664,7 +727,7 @@ public class MyClass {
调用静态方法:
```text
```java
MyClass.staticMethod(); // 通过类名直接调用静态方法
```
@ -680,7 +743,7 @@ MyClass.staticMethod(); // 通过类名直接调用静态方法
因为父类的成员变量和方法都是默认的访问修饰符可以继承给子类而子类也定义了同名的xxx发生了**变量隐藏**shadowing
```text
```java
class Parent {
int num = 10;
void display() {
@ -711,7 +774,7 @@ MyClass.staticMethod(); // 通过类名直接调用静态方法
输出:
```text
```java
Child class num: 20
Parent class num: 10
Parent class method
@ -721,7 +784,7 @@ MyClass.staticMethod(); // 通过类名直接调用静态方法
可以使用 `super` 关键字调用父类的构造方法。这通常在子类的构造方法中使用,用于显式地调用父类的构造方法。
```text
```java
class Parent {
Parent() {
System.out.println("Parent class constructor");
@ -745,7 +808,7 @@ public class Main {
输出:
```text
```java
Parent class constructor
Child class constructor
```
@ -771,7 +834,7 @@ final 关键字,意思是最终的、不可修改的,最见不得变化
3. **数据类型**变量的数据类型如int、String、class等。
4. **变量名**:变量的名称。
```text
```java
public static final int MAX_COUNT = 100; #定义常量
protected static volatile int counter; #定义成员变量
```
@ -790,7 +853,7 @@ protected static volatile int counter; #定义成员变量
**继承**
```text
```java
[修饰符] class 子类名 extends 父类名{
类体部分
}
@ -820,7 +883,7 @@ Java继承了父类**非私有**的成员变量和成员方法,但是请注意
2. **向上转型Upcasting**:动态多态;子类对象可以赋值给父类引用,这样做可以隐藏对象的真实类型,只能调用**父类中声明的方法**。
```text
```java
class Animal {
public void makeSound() {
System.out.println("Animal makes sound");
@ -856,7 +919,7 @@ Java继承了父类**非私有**的成员变量和成员方法,但是请注意
- **重载**发生在同一个类中,与继承无关;
- **重写**发生在子类中,依赖继承关系,实现运行时多态。
```text
```java
class Calculator {
int add(int a, int b) {
return a + b;
@ -879,7 +942,7 @@ class Calculator {
**必须实现抽象方法**
如果一个子类继承了抽象类,通常必须实现抽象类中的所有抽象方法,否则该子类也必须声明为抽象类。例如:
```text
```java
abstract class Animal {
// 抽象方法,没有方法体
public abstract void makeSound();
@ -908,7 +971,7 @@ class Dog extends Animal {
1. **定义一个新的子类**
创建一个子类继承抽象类并实现所有抽象方法,然后使用子类实例化对象:
```text
```java
Animal animal = new Dog();
animal.makeSound(); // 输出Dog barks
```
@ -916,7 +979,7 @@ class Dog extends Animal {
2. **使用匿名内部类**
使用匿名内部类实现抽象类相当于临时创建了一个**未命名的子类**,并且立即实例化了这个子类的对象。
```text
```java
Animal animal = new Animal() {
@Override
public void makeSound() {
@ -956,7 +1019,7 @@ class Dog extends Animal {
- 类可以实现多个接口(多继承)。
- 类只能继承一个抽象类(单继承)。
```text
```java
// 定义接口
interface Flyable {
void fly();
@ -1009,7 +1072,7 @@ public class Main {
- `void clear()`:移除集合中的所有元素。
- `boolean isEmpty()`:如果集合为空,则返回 `true`
```text
```java
import java.util.ArrayList;
import java.util.Collection;
@ -1051,7 +1114,7 @@ public class CollectionExample {
2. `next()`:返回迭代器的下一个元素,并将迭代器移动到下一个位置。
3. `remove()`:从迭代器当前位置删除元素。该方法是可选的,不是所有的迭代器都支持。
```text
```java
import java.util.ArrayList;
import java.util.Iterator;
@ -1093,7 +1156,7 @@ public class Main {
![image-20240227152019078](https://pic.bitday.top/i/2025/03/19/u6utmg-2.png)
```text
```java
// 使用 entrySet() 方法获取 Map 中所有键值对的集合,并使用增强型 for 循环遍历键值对
System.out.println("Entries in the map:");
for (Map.Entry<String, Integer> entry : map.entrySet()) {
@ -1109,7 +1172,7 @@ public class Main {
默认是小根堆输出1258
```text
```java
import java.util.PriorityQueue;
public class Main {
@ -1140,7 +1203,7 @@ public class Main {
### JAVA异常处理
```text
```java
public class ExceptionExample {
// 方法声明中添加 throws 关键字,指定可能抛出的异常类型
public static void main(String[] args) throws SomeException, AnotherException {
@ -1181,7 +1244,7 @@ Arrays.toString()
作用:方便地输出数组。
这个方法是是用来将数组转换成String类型输出的入参可以是longfloatdoubleintbooleanbyteobject 型的数组。
```text
```java
import java.util.Arrays;
public class Main {
@ -1211,7 +1274,7 @@ public class Main {
**类路径**是JVM在运行时用来查找类文件和资源文件的一组目录或JAR包。在许多项目例如Maven或Gradle项目`src/main/resources`目录下的内容在编译时会被复制到输出目录(如`target/classes``src/main/java` 下编译后的 class 文件也会放到这里。
```text
```java
MyProject/
├── src/
│ └── main/
@ -1226,7 +1289,7 @@ MyProject/
```
```text
```java
// 获取 resources 根目录下的 emp.xml 文件路径
String empFile = this.getClass().getClassLoader().getResource("emp.xml").getFile();
@ -1261,7 +1324,7 @@ String ttImgPath = resourceUrl != null ? resourceUrl.getFile() : null;
**1.获取类的字节码Class对象**:有三种方法
```text
```java
public class Test1Class{
public static void main(String[] args){
Class c1 = Student.class;
@ -1282,7 +1345,7 @@ public class Test1Class{
**2.获取类的构造器**
```text
```java
public class Cat{
private String name;
private int age;
@ -1301,7 +1364,7 @@ public class Cat{
- 获取构造器列表
```text
```java
public class TestConstructor {
@Test
@ -1386,7 +1449,7 @@ public class Test2Constructor(){
示例:`Cat` 类与测试类
```text
```java
public class Cat {
private String name;
public int age;
@ -1406,7 +1469,7 @@ public class Cat {
}
```
```text
```java
import org.junit.Test;
import java.lang.reflect.Field;
@ -1478,7 +1541,7 @@ public class FieldReflectionTest {
![image-20240307172717512](https://pic.bitday.top/i/2025/03/19/u75u7l-2.png)
```text
```java
@Test
public void testListUser(){
List<User>list=userMapper.list();
@ -1494,7 +1557,7 @@ public class FieldReflectionTest {
原理可能是:
```text
```java
//自定义注解
@Retention(RetentionPolicy.RUNTIME) //指定注解在运行时可用,这样才能通过反射获取到该注解。
@Target(ElementType.METHOD) //指定注解可用于方法上。
@ -1539,7 +1602,7 @@ public class AnnotationTest4 {
定义:
```text
```java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@ -1564,7 +1627,7 @@ public @interface MyAnnotation {
**简化使用**:当注解只有一个元素需要设置时,且该元素的名字是`value`,在使用该注解时可以不用显式地指定元素名
```text
```java
@MyAnnotation(5) // 等同于 @MyAnnotation(value = 5)
public void someMethod() {
// 方法实现
@ -1576,7 +1639,7 @@ public void someMethod() {
如果要同时设置`description`,则不能省略元素名:
```text
```java
@MyAnnotation(value = 5, description = "Specific description")
public void anotherMethod() {
// 方法实现
@ -1588,7 +1651,7 @@ public void anotherMethod() {
**获得注解上的value**反射
```text
```java
public class MyClass {
@MyAnnotation(value = "specific value")
@ -1601,7 +1664,7 @@ public class MyClass {
```text
```java
import java.lang.reflect.Method;
public class AnnotationReader {

View File

@ -15,7 +15,7 @@
- 支持多种类型的数组(如 `int[]``char[]``Object[]` 等)。
- ```text
- ```java
int[] arr1 = {1, 2, 3};
int[] arr2 = {1, 2, 3};
boolean isEqual = Arrays.equals(arr1, arr2); // true
@ -24,7 +24,7 @@
`Collections` 类本身没有直接提供类似 `Arrays.equals` 的方法来比较两个集合的内容是否相等。不过Java 中的集合类(如 `List``Set``Map`)已经实现了 `equals` 方法
- ```text
- ```java
List<Integer> list1 = Arrays.asList(1, 2, 3);
List<Integer> list2 = Arrays.asList(1, 2, 3);
List<Integer> list3 = Arrays.asList(3, 2, 1);
@ -36,25 +36,20 @@
**逻辑比较**
```text
```java
boolean flag = false;
if (!flag) { //! 是 Java 中的逻辑非运算符,只能用于对布尔值取反。
System.out.println("flag 是 false");
}
if (flag == false) { //更常用!
System.out.println("flag 是 false");
}
//java中没有 if(not flag) 这种写法!
```
### 常用数据结构
#### `String`
@ -71,7 +66,7 @@ if (flag == false) { //更常用!
需要String先转为char [] 数组排序好之后再转为String类型
```text
```java
char[] charArray = str.toCharArray();
Arrays.sort(charArray);
String sortedStr = new String(charArray);
@ -92,12 +87,51 @@ String sortedStr = new String(charArray);
#### **`HashMap`**
#### `StringBuffer`
`StringBuffer` 是 Java 中用于操作可变字符串的类
**append**
```java
public class StringBufferExample {
public static void main(String[] args) {
// 创建初始字符串 "Hello"
StringBuffer sb = new StringBuffer("Hello");
System.out.println("Initial: " + sb.toString()); // 输出 "Hello"
// 1. append在末尾追加 " World"
sb.append(" World");
System.out.println("After append: " + sb.toString()); // 输出 "Hello World"
// 2. insert在索引 5 位置("Hello"后)插入 ", Java"
sb.insert(5, ", Java");
System.out.println("After insert: " + sb.toString()); // 输出 "Hello, Java World"
// 3. delete删除从索引 5 到索引 11不包含的子字符串即删除刚才插入的 ", Java"
sb.delete(5, 11);
//sb.delete(5, sb.length()); 删除到末尾
System.out.println("After delete: " + sb.toString()); // 输出 "Hello World"
// 4. deleteCharAt删除索引 5 处的字符(删除空格)
sb.deleteCharAt(5);
System.out.println("After deleteCharAt: " + sb.toString()); // 输出 "HelloWorld"
// 5. reverse反转整个字符串
sb.reverse();
System.out.println("After reverse: " + sb.toString()); // 输出 "dlroWolleH"
}
}
```
#### `HashMap`
- 基于哈希表实现,查找、插入和删除的平均时间复杂度为 O(1)。
- 不保证元素的顺序。
```text
```java
import java.util.HashMap;
import java.util.Map;
@ -137,7 +171,7 @@ public class HashMapExample {
记录二维数组中某元素是否被访问过,推荐使用:
```text
```java
int m = grid.length;
int n = grid[0].length;
boolean[][] visited = new boolean[m][n];
@ -150,13 +184,13 @@ visited[i][j] = true;
#### **`HashSet`**
#### `HashSet`
- 基于哈希表实现,查找、插入和删除的平均时间复杂度为 O(1)。
- 不保证元素的顺序!!因此不太用iterator迭代而是用contains判断是否有xx元素。
```text
```java
import java.util.HashSet;
import java.util.Set;
@ -221,7 +255,7 @@ visited[i][j] = true;
6. **`clear()`**
- 清空队列。
```text
```java
import java.util.PriorityQueue;
import java.util.Comparator;
@ -281,7 +315,7 @@ public class PriorityQueueExample {
- 访问元素的时间复杂度为 O(1),在末尾插入和删除的时间复杂度为 O(1)。
- 在指定位置插入和删除O(n) `add(int index, E element)` `remove(int index)`
```text
```java
import java.util.ArrayList;
import java.util.List;
@ -324,7 +358,7 @@ public class ArrayListExample {
**如果事先不知道嵌套列表的大小如何遍历呢?**
```text
```java
import java.util.ArrayList;
import java.util.List;
@ -359,7 +393,7 @@ for (int i = 0; i < list.size(); i++) {
- **快速访问**:通过索引访问元素的时间复杂度为 O(1)。
- **连续内存**:数组的元素在内存中是连续存储的。
```text
```java
public class ArrayExample {
public static void main(String[] args) {
// 创建数组
@ -429,7 +463,7 @@ public class ArrayExample {
#### `二维数组`
```text
```java
int rows = 3;
int cols = 3;
int[][] array = new int[rows][cols];
@ -467,7 +501,7 @@ public void setZeroes(int[][] matrix) {
队尾插入,队头取!
```text
```java
import java.util.Queue;
import java.util.LinkedList;
@ -508,7 +542,7 @@ public class QueueExample {
**栈**
```text
```java
Deque<Integer> stack = new ArrayDeque<>();
stack.push(1); // 入栈
Integer top1=stack.peek()
@ -541,7 +575,7 @@ Integer top = stack.pop(); // 出栈
*删除或查看元素*:调用 `remove()``poll()` 时,则是调用 `removeFirst()``pollFirst()`,即在队头移除元素;同理,`element()``peek()` 则是查看队头元素。
```text
```java
import java.util.Deque;
import java.util.LinkedList;
@ -591,7 +625,7 @@ public class DequeExample {
2. `next()`:返回迭代器的下一个元素,并将迭代器移动到下一个位置。
3. `remove()`:从迭代器当前位置删除元素。该方法是可选的,不是所有的迭代器都支持。
```text
```java
import java.util.ArrayList;
import java.util.Iterator;
@ -625,7 +659,7 @@ public class Main {
#### **数组排序**
```text
```java
import java.util.Arrays;
public class ArraySortExample {
@ -641,7 +675,7 @@ public class ArraySortExample {
#### 集合排序
```text
```java
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -678,7 +712,7 @@ public class ListSortExample {
- 如果返回零,说明 `o1` 等于 `o2`
- 如果返回正数,说明 `o1` 排在 `o2`后面。
```text
```java
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@ -725,7 +759,7 @@ public class ComparatorSortExample {
**自定义比较器排序二维数组** 用Lambda表达式实现`Comparator<int[]>接口`
```text
```java
import java.util.Arrays;
public class IntervalSort {
@ -771,18 +805,13 @@ public class IntervalSort {
#### 双指针
1. 问题分析
题型
- 确定问题是否涉及数组或链表的遍历。
- 判断是否需要通过两个指针的协作来缩小搜索范围或比较元素。
- 同向双指针:两个指针从同一侧开始移动,通常用于**滑动窗口**或链表问题。
- 对向双指针:两个指针从两端向中间移动,通常用于有序数组或回文问题。重点是考虑**移动哪个指针**可能优化结果!!!
- 快慢指针:两个指针以不同速度移动,通常用于链表中的环检测或中点查找。
2. 选择双指针类型:
- **同向双指针**:两个指针从同一侧开始移动,通常用于**滑动窗口**或链表问题。
- **对向双指针**:两个指针从两端向中间移动,通常用于有序数组或回文问题。重点是考虑**移动哪个指针**可能优化结果!!!
- **快慢指针**:两个指针以不同速度移动,通常用于链表中的环检测或中点查找。
3. 适用场景
适用场景:
**有序数组的两数之和**
@ -881,7 +910,7 @@ public void inOrderTraversalIterative(TreeNode root, List<Integer> list) {
*迭代法前序*
```
```java
public void preOrderTraversalIterative(TreeNode root, List<Integer> list) {
if (root == null) return;
@ -904,3 +933,97 @@ public void preOrderTraversalIterative(TreeNode root, List<Integer> list) {
}
```
层序遍历BFS
```java
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> result = new ArrayList<>();
if (root == null) return result;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int levelSize = queue.size();
List<Integer> level = new ArrayList<>();
for (int i = 0; i < levelSize; i++) {
TreeNode node = queue.poll();
level.add(node.val);
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
result.add(level);
}
return result;
}
```
#### 回溯法
回溯算法用于 **搜索一个问题的所有的解** ,即爆搜(暴力解法),通过深度优先遍历的思想实现。核心思想是:
**1.逐步构建解答:**
回溯算法通过逐步构造候选解,当构造的部分解满足条件时继续扩展;如果发现当前解不符合要求,则“回溯”到上一步,尝试其他可能性。
**2.剪枝Pruning**
在构造候选解的过程中,算法会判断当前部分解是否有可能扩展成最终的有效解。如果判断出无论如何扩展都不可能得到正确解,就立即停止继续扩展该分支,从而节省计算资源。
**3.递归调用**
回溯通常通过递归来实现。递归函数在**每一层都尝试不同的选择**,并在尝试失败或达到终点时返回上一层重新尝试其他选择。
**例:以数组 `[1, 2, 3]` 的全排列为例。**
先写以 1 开头的全排列,它们是:`[1, 2, 3], [1, 3, 2]`,即 `1` + `[2, 3]` 的全排列(注意:递归结构体现在这里);
再写以 2 开头的全排列,它们是:`[2, 1, 3]`, `[2, 3, 1]`,即 `2` + `[1, 3]` 的全排列;
最后写以 3 开头的全排列,它们是:`[3, 1, 2]`, `[3, 2, 1]`,即 `3` + `[1, 2]` 的全排列。
![image-20250326095409631](https://pic.bitday.top/i/2025/03/26/fs3bz0-0.png)
```java
public class Permute {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
// 用来标记数组中数字是否被使用
boolean[] used = new boolean[nums.length];
List<Integer> path = new ArrayList<>();
backtrack(nums, used, path, res);
return res;
}
private void backtrack(int[] nums, boolean[] used, List<Integer> path, List<List<Integer>> res) {
// 当path中元素个数等于nums数组的长度时说明已构造出一个排列
if (path.size() == nums.length) {
res.add(new ArrayList<>(path));
return;
}
// 遍历数组中的每个数字
for (int i = 0; i < nums.length; i++) {
// 如果该数字已经在当前排列中使用过,则跳过
if (used[i]) {
continue;
}
// 选择数字nums[i]
used[i] = true;
path.add(nums[i]);
// 递归构造剩余的排列
backtrack(nums, used, path, res);
// 回溯:撤销选择,尝试其他数字
path.remove(path.size() - 1);
used[i] = false;
}
}
}
```

View File

@ -31,7 +31,25 @@
| 10 | orders | 订单表 |
| 11 | order_detail | 订单明细表 |
###  @TableName("user")public class User {    @TableId    private Long id;    private String name;    private Integer age;    @TableField("isMarried")    private Boolean isMarried;    @TableField("`order`")    private String order;}Java
```java
@TableName("user")
public class User {
@TableId
private Long id;
private String name;
private Integer age;
@TableField("isMarried")
private Boolean isMarried;
@TableField("`order`")
private String order;
}
```
**1.nginx 反向代理的好处:**
@ -47,7 +65,7 @@
因为一般后台服务地址不会暴露所以使用浏览器不能直接访问可以把nginx作为请求访问的入口请求到达nginx后转发到具体的服务中从而保证后端服务的安全。
```text
```java
server{
listen 80;
server_name localhost;
@ -62,7 +80,7 @@ server{
**2.负载均衡配置**(有两个后端服务器)
```text
```java
upstream webservers{
server 192.168.100.128:8080;
server 192.168.100.129:8080;
@ -93,7 +111,7 @@ server{
在pom.xml中添加依赖
```xml
```java
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
@ -156,7 +174,7 @@ protected void addResourceHandlers(ResourceHandlerRegistry registry) {
EmployeeLoginDTO.java
```text
```java
@Data
@ApiModel(description = "员工登录时传递的数据模型")
public class EmployeeLoginDTO implements Serializable {
@ -188,7 +206,7 @@ spring security中提供了一个加密类BCryptPasswordEncoder。
- 添加依赖
```text
```java
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
@ -197,7 +215,7 @@ spring security中提供了一个加密类BCryptPasswordEncoder。
- 添加配置
```text
```java
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@ -218,7 +236,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
- 使用
```text
```java
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
@ -256,7 +274,7 @@ ThreadLocal为**每个线程**提供**单独**一份存储空间,具有线程
**每次请求代表一个线程**请求可以先经过拦截器再经过controller=>service=>mapper,都是在一个线程里。
```text
```java
public class BaseContext {
public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
@ -321,7 +339,7 @@ public class BaseContext {
JacksonObjectMapper()文件:
```text
```java
public class JacksonObjectMapper extends ObjectMapper {
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
@ -373,7 +391,7 @@ public void startOrStop(Integer status, Long id) {
还有一种把源对象source的属性值赋给目标**对象**target中与源**对象**source的中有着同属性名的属性
```text
```java
BeanUtils.copyProperties(source,target);
```
@ -397,7 +415,7 @@ BeanUtils.copyProperties(source,target);
在 EmployeeMapper.xml 中编写SQL
```sql
```java
<update id="update" parameterType="Employee">
update employee
<set>
@ -454,7 +472,7 @@ BeanUtils.copyProperties(source,target);
**1). 导入Spring Data Redis的maven坐标(已完成)**
```xml
```java
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
@ -465,7 +483,7 @@ BeanUtils.copyProperties(source,target);
在application-dev.yml中添加
```yaml
```java
sky:
redis:
host: localhost
@ -482,7 +500,7 @@ database:指定使用Redis的哪个数据库Redis服务启动后默认有16
在application.yml中添加读取application-dev.yml中的相关Redis配置
```yaml
```java
spring:
profiles:
active: dev
@ -564,7 +582,7 @@ public class SpringDataRedisTest {
**哈希测试**
```text
```java
/**
* 操作哈希类型的数据
*/
@ -723,7 +741,7 @@ public class SpringDataRedisTest {
```text
```java
public static String doGet(String url,Map<String,String> paramMap){
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
@ -798,7 +816,7 @@ public static String doGet(String url,Map<String,String> paramMap){
- 每个分类下的菜品保存一份缓存数据
- 数据库中菜品数据有**变更时清理缓存数据**
```text
```java
@Autowired
private RedisTemplate redisTemplate;
/**
@ -845,7 +863,7 @@ public static String doGet(String url,Map<String,String> paramMap){
清理缓冲方法:
```text
```java
private void cleanCache(String pattern){
Set keys = redisTemplate.keys(pattern);
redisTemplate.delete(keys);
@ -858,7 +876,7 @@ public static String doGet(String url,Map<String,String> paramMap){
Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。
```text
```java
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId> <version>2.7.3</version>
@ -892,7 +910,7 @@ Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要
```text
```java
@PostMapping
@CachePut(value = "userCache", key = "#user.id")//key的生成userCache::1
public User save(@RequestBody User user){
@ -915,7 +933,7 @@ Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要
所以,@Cacheable(cacheNames = "userCache",key="#id")中的#id表示的是函数形参中的id而不能是返回值中的user.id
```text
```java
@GetMapping
@Cacheable(cacheNames = "userCache",key="#id")
public User getById(Long id){
@ -928,7 +946,7 @@ Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要
作用: 清理指定缓存
```text
```java
@DeleteMapping
@CacheEvict(cacheNames = "userCache",key = "#id")//删除某个key对应的缓存数据
public void deleteById(Long id){
@ -990,13 +1008,13 @@ https://pay.weixin.qq.com/static/product/product_index.shtml
输入代码:
```text
```java
cpolar.exe authtoken ZmIwMmQzZDYtZDE2ZS00ZGVjLWE2MTUtOGQ0YTdhOWI2M2Q1
```
3获取临时域名
```text
```java
cpolar.exe http 8080
```
@ -1058,7 +1076,7 @@ cron表达式在线生成器https://cron.qqe2.com/
```text
```java
@Component
@Slf4j
public class OrderTask {