高频面试手撕
手撕高频结构
前言
以下内容,都是博主在秋招面试中,遇到的面试手撕代码题目,不同于算法题目,更多考察的是基础知识,包含常见的数据结构比如线性表、哈希表、优先级队列等,还有多线程以及数据库连接池等内容。
1、ArrayList
-
实现了
ArrayList
的基本功能,包括随机访问和自动扩容。 -
添加元素时,如果数组容量不足,会自动扩容,避免频繁的手动扩展操作。
-
能够处理常见的越界检查、扩容和元素添加。
public class MyArrayList<T> {private T[] elements; // 用于存储元素的数组private int size; // 当前ArrayList中实际元素的个数// 默认初始容量private static final int DEFAULT_CAPACITY = 10;// 无参构造函数,使用默认初始容量public MyArrayList() {elements = (T[]) new Object[DEFAULT_CAPACITY];size = 0;}// 带初始容量的构造函数public MyArrayList(int initialCapacity) {if (initialCapacity <= 0) {throw new IllegalArgumentException("初始容量必须大于0");}elements = (T[]) new Object[initialCapacity];size = 0;}// 添加元素方法(自动扩容)public void add(T element) {ensureCapacity(); // 检查是否需要扩容elements[size++] = element; // 将元素添加到数组中,并更新size}// 获取元素方法,根据索引随机访问元素public T get(int index) {checkIndex(index); // 检查索引是否越界return elements[index];}// 返回当前ArrayList的大小public int size() {return size;}// 扩容方法,将数组容量增加1.5倍private void ensureCapacity() {if (size == elements.length) {int newCapacity = elements.length * 1.5;elements = Arrays.copyOf(elements, newCapacity); // 扩容}}// 检查索引是否越界的方法private void checkIndex(int index) {if (index < 0 || index >= size) {throw new IndexOutOfBoundsException("索引超出范围: " + index);}}// 重写toString方法,方便输出查看@Overridepublic String toString() {return Arrays.toString(Arrays.copyOf(elements, size));}// 测试MyArrayList的功能public static void main(String[] args) {MyArrayList<Integer> list = new MyArrayList<>();// 添加元素list.add(10);list.add(20);list.add(30);list.add(40);// 打印列表System.out.println("ArrayList内容: " + list);// 随机访问元素System.out.println("索引1的元素: " + list.get(1));// 添加更多元素,测试扩容for (int i = 0; i < 10; i++) {list.add(i * 10);}// 打印扩容后的列表System.out.println("扩容后的ArrayList内容: " + list);System.out.println("ArrayList大小: " + list.size());}
}
2、LinkedList
底层是链表
public class MyLinkedList {// 链表节点类static class Node {int data; // 节点的数据Node next; // 指向下一个节点的指针// 构造函数public Node(int data) {this.data = data;this.next = null;}}private Node head; // 链表的头节点// 构造函数,初始化空链表public MyLinkedList() {this.head = null;}// 1. 在链表的头部插入节点public void addFirst(int data) {Node newNode = new Node(data);newNode.next = head; // 新节点指向当前头节点head = newNode; // 头节点更新为新节点}// 2. 在链表的尾部插入节点public void addLast(int data) {Node newNode = new Node(data);if (head == null) {head = newNode; // 如果链表为空,则新节点为头节点} else {Node cur = head;while (cur.next != null) {cur = cur.next; // 找到最后一个节点}cur.next = newNode; // 将新节点插入到最后}}// 3. 查找链表中是否存在某个数据public boolean contains(int key) {Node cur = head;while (cur != null) {if (cur.data == key) {return true; // 找到返回 true}cur = cur.next;}return false; // 未找到返回 false}// 4. 删除链表中首次出现的指定数据public void remove(int key) {if (head == null) {return; // 链表为空,直接返回}// 如果删除的是头节点if (head.data == key) {head = head.next; // 头节点指向下一个节点return;}// 遍历链表,找到要删除的节点Node prev = null;Node cur = head;while (cur != null && cur.data != key) {prev = cur;cur = cur.next;}// 如果找到要删除的节点if (cur != null) {prev.next = cur.next; // 前一个节点的 next 指向当前节点的下一个节点}}// 5. 获取链表的长度public int size() {int count = 0;Node cur = head;while (cur != null) {count++;cur = cur.next;}return count;}// 6. 打印链表public void printList() {Node cur = head;while (cur != null) {System.out.print(cur.data + " -> ");cur = cur.next;}System.out.println("null");}// 7. 清空链表public void clear() {head = null;}// 测试代码public static void main(String[] args) {MyLinkedList list = new MyLinkedList();list.addFirst(1);list.addFirst(2);list.addLast(3);list.addLast(4);list.printList(); // 打印链表: 2 -> 1 -> 3 -> 4 -> nullSystem.out.println("List size: " + list.size()); // 输出链表长度: 4System.out.println("Contains 3? " + list.contains(3)); // 输出 trueSystem.out.println("Contains 5? " + list.contains(5)); // 输出 falselist.remove(1); // 删除 1list.printList(); // 打印链表: 2 -> 3 -> 4 -> nulllist.clear(); // 清空链表list.printList(); // 打印链表: null}
}
3、Stack栈
先进后出
public class MyStack {public int[] elem;public int usedSize;public static final int DEFAULT_CAPACITY=10;public MyStack() {elem=new int[DEFAULT_CAPACITY];}/*** 入栈* @param val*/public void push(int val) {//先判断栈是否满了if(isFull()) {elem= Arrays.copyOf(elem,2*elem.length);}elem[usedSize++]=val;}/*** 判断当前栈是否满了* @return*/public boolean isFull() {if(usedSize==elem.length) {return true;}return false;}/*** 删除栈顶元素*/public int pop() {if(isEmpty()) {throw new RuntimeException("栈空了");}int val= elem[usedSize-1];usedSize--;return val;}/*** 是否为空* @return*/public boolean isEmpty() {return usedSize==0;}/*** 获取栈顶元素但不删除* @return*/public int peek() {if(isEmpty()) {throw new RuntimeException("栈为空了!");}return elem[usedSize-1];}
}
4、Queue队列
先进先出
public class MyQueue {static class Node {public int val;public Node next;public Node(int val) {this.val = val;}}public Node head;//队列的头public Node tail;//队列的尾/*** 入队操作* @param val*/public void offer(int val) {Node node=new Node(val);if(head==null) {head=node;tail=node;}else {tail.next=node;tail=tail.next;}}/*** 出队操作*/public int poll() {if(head==null)throw new RuntimeException("队列为空!");int val= head.val;;if(head.next==null)head=tail=null;elsehead=head.next;return val;}/*** 查看队头元素*/public int peek() {if(head==null) {throw new RuntimeException("队列为空!");}return head.val;}
}
5、优先级队列(大根堆)
队列是一种先入先出的数据结构,但是如果队列中的元素带有优先级,就可能需要让优先级高的元素先出队列
这种情况下就有了优先级队列这种数据结构,这种结构提供了两个基本操作,一是返回最高优先级对象,二是添加新的对象
PriorityQueue的底层使用了堆的数据结构,堆其实就是一棵完全二叉树,若该完全二叉树的每棵子树都是根结点最大,叫做大根堆(否则叫小根堆)
public class Heap {public int[] elem;public int usedSize;// 当前堆中有效元素个数public Heap() {this.elem=new int[10];}public void initArray(int[] array) {elem= Arrays.copyOf(array,array.length);usedSize=elem.length;}/*** 建堆* 时间复杂度:O(n)*/public void createHeap() {for (int parent = (usedSize-1-1)/2; parent >=0 ; parent--) {shiftDown(parent,usedSize);// usedSize保证所有子树的下标都不会比它大,可比较用于所有子树的结束}}/*** 向下调整 让每棵子树都成为大根堆* @param parent 每棵子树的根结点下标* @param len 所有子树的结束位置(usedSize)*/private void shiftDown(int parent,int len) {int child=2*parent+1;while (child<len) {// 存在右孩子的情况下,比较左右孩子的大小,child记录较大值的下标if(child+1<len&&elem[child]<elem[child+1]) {child++;}// 此时child记录的是孩子中的较大值,再去与父节点进行比较if(elem[child]>elem[parent]) {swap(elem,child,parent);// 向下调整,让parent到child的位置,继续往下做比较parent=child;child=2*parent+1;}else {// 如果走到else,说明此时该子树符合大根堆结构,不需要再做向下调整,直接跳出循环即可break;}}}private void swap(int[] array,int i,int j) {int tmp=array[i];array[i]=array[j];array[j]=tmp;}/*** 入队(插入元素)* 【插入末尾位置,然后向上调整结构】* @param x*/public void offer(int x) {if(isFull()) {elem=Arrays.copyOf(elem,elem.length*2);}this.elem[usedSize]=x;shiftUp(usedSize);usedSize++;}private boolean isFull() {return usedSize== elem.length;}/*** 向上调整* @param child 子节点下标*/private void shiftUp(int child) {// 找到其父节点int parent=(child-1)/2;// 向上调整一直到根节点结束while (child>0) {// 判断子节点与父节点大小if(elem[child]>elem[parent]) {swap(elem,child,parent);child=parent;parent=(child-1)/2;}else {// 若不需要调整,则直接跳出循环break;}}}/*** 出队(删除元素)* 【交换堆顶与队尾元素,删除队尾元素,再让堆顶做向下调整】* @return*/public int poll() {if(isEmpty()) {return -1;}int old=elem[0];// 交换堆顶与堆尾元素swap(elem,0,usedSize-1);// 删除堆尾元素usedSize--;// 将堆顶元素向下调整shiftDown(0,usedSize);return old;}/*** 返回堆顶最大元素* @return*/public int peek() {if(isEmpty()) {return -1;}int val=elem[0];return val;}public boolean isEmpty() {return usedSize==0;}/*** 堆排序* 1、将堆顶元素【最大值】放到末尾,剩余部分做向下调整* 2、持续遍历所有操作,完成堆排序,大顶堆通过堆排序后得到升序数组* 时间复杂度 O(n logn) ;* 空间复杂度 O(1)*/public void heapSort() {int end=usedSize-1;while (end>0) {swap(elem,0,end);shiftDown(0,end);end--;}}public static void main(String[] args) {Heap heap=new Heap();// 初始化数组并创建堆int[] array={10,20,15,30,40,25,50};System.out.println("初始化堆");heap.initArray(array); // 初始化数据heap.createHeap(); // 建堆System.out.println("初始最大堆:"+Arrays.toString(Arrays.copyOfRange(heap.elem,0,heap.usedSize)));heap.offer(35);System.out.println("插入后最大堆:"+Arrays.toString(Arrays.copyOfRange(heap.elem,0,heap.usedSize)));heap.poll();System.out.println("弹出最大元素后最大堆:"+Arrays.toString(Arrays.copyOfRange(heap.elem,0,heap.usedSize)));heap.heapSort();System.out.println("堆排序结果:"+Arrays.toString(Arrays.copyOfRange(heap.elem,0,heap.usedSize)));}
}
//
初始化堆
初始最大堆:[50, 40, 25, 30, 20, 10, 15]
插入后最大堆:[50, 40, 25, 35, 20, 10, 15, 30]
弹出最大元素后最大堆:[40, 35, 25, 30, 20, 10, 15]
堆排序结果:[10, 15, 20, 25, 30, 35, 40]Process finished with exit code 0
6、HashMap
用拉链法解决冲突,实现了常见的方法
public class MyQueue {static class Node {public int val;public Node next;public Node(int val) {this.val = val;}}public Node head;//队列的头public Node tail;//队列的尾/*** 入队操作* @param val*/public void offer(int val) {Node node=new Node(val);if(head==null) {head=node;tail=node;}else {tail.next=node;tail=tail.next;}}/*** 出队操作*/public int poll() {if(head==null)throw new RuntimeException("队列为空!");int val= head.val;;if(head.next==null)head=tail=null;elsehead=head.next;return val;}/*** 查看队头元素*/public int peek() {if(head==null) {throw new RuntimeException("队列为空!");}return head.val;}
}
7、生产者消费者模型
生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取。
该模型有以下两个用途:
1)削峰填谷
阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
三峡大坝,汛期控制水量,防止水灾;旱期释放积攒的水,防止旱灾。
2)解耦合
阻塞队列也能使生产者和消费者之间解耦(减少两者之间的关联关系)
过年一家子一起包饺子,一般有明确的分工,一个人负责擀饺子皮,其他人负责包,擀饺子皮的人就是“生产者”,包饺子的人就是“消费者”,擀饺子皮的人不关心包饺子的人是谁,包饺子的人也不关心擀饺子皮的人是谁。
代码关键点总结
- 生产者-消费者模型:生产者生成数据并放入队列,消费者从队列中取数据进行处理。
BlockingQueue
自动处理了队列为空或满时的阻塞问题,简化了多线程编程中的同步控制。 - 线程安全:
LinkedBlockingQueue
是线程安全的,它内部使用了锁机制来保证线程之间对队列的安全访问。 - 无限循环的消费者线程:消费者线程在
while(true)
中不断取数据,因此只要有生产者继续生产,消费者就会不断消费。 Thread.sleep(1000)
模拟生产过程的延迟:生产者每次生产一个元素后会等待1秒,模拟一个耗时的生产过程。
public static void main(String[] args) {BlockingQueue<Integer> queue=new LinkedBlockingQueue<>();Thread consumer=new Thread() {@Overridepublic void run() {while (true) {try {Integer value=queue.take();System.out.println("消费元素:"+value);} catch (InterruptedException e) {e.printStackTrace();}}}};consumer.start();Thread producer=new Thread() {@Overridepublic void run() {for (int i = 0; i < 10000; i++) {System.out.println("生产了元素:"+i);try {queue.put(i);Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}};producer.start();try {consumer.join(); // join()方法的作用是等待线程终止producer.join(); // 由于消费者线程是一个无限循环,实际运行中,主线程将会永远阻塞在consumer.join()上。} catch (InterruptedException e) {e.printStackTrace();}
}
8、BlockingQueue
阻塞队列是一种特殊的队列. 也遵守 “先进先出” 的原则.
阻塞队列是一种线程安全的数据结构, 并且具有以下特性:
当队列满的时候, 继续入队列就会阻塞, 直到有其他线程从队列中取走元素.
当队列空的时候, 继续出队列也会阻塞, 直到有其他线程往队列中插入元素.
public class Main {static class BlockingQueue {//1000就相当于队列的最大容量,此处暂不考虑扩容问题private int[] items=new int[1000];private volatile int head=0;private volatile int tail=0;private volatile int size=0;private Object locker=new Object();//put用来入队列public void put(int item) throws InterruptedException {//因为队列中涉及修改操作,所以通过加锁来解决线程不安全问题(原子性)。synchronized (locker) {//使用while就是为了让wait被唤醒之后,再次确认条件是否成立while (size==items.length) {//队列已经满了,对于阻塞队列来说就要阻塞locker.wait();}items[tail]=item;tail++;//如果到达末尾,就回到起始位置if(tail>=items.length) {tail=0;}size++;locker.notify();}}public int take() throws InterruptedException {int ret=0;synchronized (locker) {while (size==0) {//对于阻塞队列来说,如果队列为空,在尝试获取元素,就要阻塞locker.wait();}ret=items[head];head++;if(head>=items.length) {head=0;}size--;//此处的notify用来唤醒put中的waitlocker.notify();}return ret;}}public static void main(String[] args) throws InterruptedException {BlockingQueue queue=new BlockingQueue();//消费者模型Thread consumer=new Thread() {@Overridepublic void run() {while (true) {try {int elem= queue.take();System.out.println("消费者元素:"+elem);} catch (InterruptedException e) {e.printStackTrace();}}}};consumer.start();//生产者线程Thread producer=new Thread() {@Overridepublic void run() {for (int i = 0; i < 10000; i++) {System.out.println("生产元素:"+i);try {queue.put(i);Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}};producer.start();consumer.join();producer.join();}
}
9、多线程顺序打印ABC
-
锁与条件变量:我们使用一个
lock
对象来保证线程间的同步,所有线程共享这个锁。 -
状态控制:通过一个
state
变量控制当前该哪个线程执行。state
的取值为0
、1
、2
,分别代表线程A、B、C。 -
同步块与等待机制:
-
使用
synchronized
来保证同一时间只有一个线程能访问共享资源。 -
使用
wait()
和notifyAll()
来使得线程在不符合条件时等待,并在条件满足时通知其他线程。
-
-
执行结果:
每次运行该程序,三个线程会顺序打印 "ABCABCABC..."
,直到打印10次结束。
public class PrintABC {private static final Object lock = new Object();private static int state = 0; // 0: A, 1: B, 2: Cpublic static void main(String[] args) {Thread threadA = new Thread(new PrintTask("A", 0));Thread threadB = new Thread(new PrintTask("B", 1));Thread threadC = new Thread(new PrintTask("C", 2));threadA.start();threadB.start();threadC.start();}static class PrintTask implements Runnable {private String name;private int flag; // 用于标识当前线程的顺序public PrintTask(String name, int flag) {this.name = name;this.flag = flag;}@Overridepublic void run() {try {for (int i = 0; i < 10; i++) { // 打印10次ABCsynchronized (lock) {while (state != flag) {lock.wait(); // 如果不是当前线程的轮次,则等待}System.out.print(name); // 打印当前线程对应的字符state = (state + 1) % 3; // 更新状态,确保下一个线程打印lock.notifyAll(); // 唤醒其他线程}}} catch (InterruptedException e) {e.printStackTrace();}}}
}
11、线程池
步骤:
- 使用一个
BlockingQueue
组织所有任务 - 核心操作为
submit
,将任务加入线程池阻塞队列中,并创建线程 - 一个线程池可用同时提交N个任务,对应线程池中有M个线程来负责完成这N个任务,利用生产者消费者模型,把N个任务分配给M个线程
public class MyThreadPool {private BlockingQueue<Runnable> queue=new LinkedBlockingQueue<>();public MyThreadPool(int m) {// 在构造方法中,创建出m个线程,负责完成工作for (int i = 0; i < m; i++) {Thread t=new Thread(()->{while (true) {try {Runnable runnable=queue.take();runnable.run();} catch (InterruptedException e) {e.printStackTrace();}}});t.start();}}// 将任务加入线程池阻塞队列中public void submit(Runnable runnable) throws InterruptedException {queue.put(runnable);}public static void main(String[] args) throws InterruptedException {MyThreadPool pool=new MyThreadPool(10);for (int i = 0; i < 1000; i++) {int taskId=i;pool.submit(new Runnable() {@Overridepublic void run() {System.out.println("执行当前任务:"+taskId+"当前线程:"+Thread.currentThread().getName());}});}}
}
12、数据库连接池
步骤:
1、创建固定数量的数据库连接并保存到一个集合中
2、提供getConnection()
方法从池中获取连接
3、提供releaseConnection()
方法将使用完的连接返回到池中
4、实现线程安全的连接获取和释放
public class ConnectionPool {private List<Connection> connectionPool;private int poolSize=10; // 池中连接数量private String url="jdbc:mysql://localhost:3306/test"; // 数据库URLprivate String username="root"; // 数据库用户名private String password="password"; // 数据库密码// 构造函数,初始化连接池public ConnectionPool() {connectionPool=new ArrayList<>();try {// 加载数据库驱动Class.forName("com.mysql.cj.jdbc.Driver");// 初始连接池for (int i = 0; i < poolSize; i++) {connectionPool.add(DriverManager.getConnection(url,username,password));}} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();}}// 从池中获取连接public synchronized Connection getConnection() {// 如果池中有可用连接,返回第一个连接if(!connectionPool.isEmpty()) {return connectionPool.remove(0);}else {// 如果池中没有可用连接,返回 null或抛出异常System.out.println("连接池已用完,无法提供连接");return null;}}// 释放连接,将连接返回到池中public synchronized void releaseConnection(Connection connection) {if(connection!=null) {connectionPool.add(connection); // 归还连接到池中}}// 关闭连接池中的所有连接public synchronized void closeAllConnections() {for (Connection connection:connectionPool) {try {connection.close();}catch (SQLException e) {e.printStackTrace();}}}// 获取连接池的当前大小public int getCurrentPoolSize() {return connectionPool.size();}public static void main(String[] args) {ConnectionPool pool=new ConnectionPool();// 获取一个连接Connection connection=pool.getConnection();// 假设进行了一些数据库操作// 使用完后将连接返回到池中pool.releaseConnection(connection);// 打印连接池剩余连接数System.out.println("当前连接池大小:"+pool.getCurrentPoolSize());// 关闭连接池pool.closeAllConnections();}
}
改进空间:
- 连接池动态扩展:目前连接池的大小是固定的,实际生产环境中可以根据需求动态扩展或缩减连接池的大小。
- 连接池维护:可以添加心跳检测,自动关闭不可用的连接并替换。
- 最大等待时间:如果连接池耗尽,可以设置最大等待时间,并且在超时后抛出异常。
相关文章:

高频面试手撕
手撕高频结构 前言 以下内容,都是博主在秋招面试中,遇到的面试手撕代码题目,不同于算法题目,更多考察的是基础知识,包含常见的数据结构比如线性表、哈希表、优先级队列等,还有多线程以及数据库连接池等内…...

Spring Boot 3.3 【八】整合实现高可用 Redis 集群
一、引言 在当今快速发展的软件开发领域,系统的性能和可靠性至关重要。Springboot 3 整合 Redis 7 集群具有多方面的重大意义。 首先,随着业务的不断发展,数据量呈爆炸式增长,单个 Redis 服务器往往难以满足存储和处理需求。Red…...
循环控制结构穷举 同构数
说明 同构数是会出现在它的平方的右边的数。例如,5就是1个同构数。5的平方是25,25最右边的这个数是5自己。25也是一个同构数,比如25的平方是625,而625右边的数是25. 请编程输出1000以内正整数中所有的同构数。每行一个答案。 输…...
主机本地IP与公网IP以及虚拟机的适配器和WSL发行版的IP
在局域网内,如果你想要连接到同一网络中的另一台设备,建议使用 本地 IP 地址(也称为局域网 IP 地址)。这是因为本地 IP 地址是在局域网内分配给设备的,用于在同一网络中的设备之间进行通信。 使用本地 IP 地址的好处 …...
@MassageMapping和@SendTo注解详解
MessageMapping注解是Spring Framework中用于WebSocket消息处理的注解,它用于将特定的消息路径映射到处理器方法上。SendTo注解指定了相应消息应该被发送到的目的地路径。 一、WebSocket配置类: Configuration EnableWebSocketMessageBroker public cl…...

2.1_Linux发展与基础
Linux基础知识 Shell 命令执行环境: 命令提示符的组成:(用户名主机名)-[当前路径]权限提示符,例:(kali㉿kali)-[~]$ ~ 表示所在目录为家目录:其中root用户的家目录是/root,普通用户的家目录在/home下 # 表示用户的权…...

c#子控件拖动父控件方法及父控件限在窗体内拖动
一、效果 拖放位置不超过窗体四边,超出后自动靠边停靠支持多子控件拖动指定控件拖放(含父控件或窗体)点击左上角logo弹出消息窗口(默认位置右下角)1.1 效果展示 1.2 关于MQTTnet(最新版v4.3.7.1207)实现在线客服功能,见下篇博文 https://github.com/dotnet/MQTTnet 网上…...

Redis --- 第八讲 --- 关于主从复制哨兵
主从复制的补充问题 从节点和主节点之间断开连接,有两种情况: 1、从节点和主节点断开连接 slaveof no one 命令。这个时候,从节点就能能够晋升成主节点。意味着我们程序员要主动修改redis的组成结构。, 2、主节点挂了 这个时…...

【数据结构】时间和空间复杂度-Java
如何衡量算法的好坏 根据时间复杂度和空间复杂度来判断 比较项目时间复杂度空间复杂度定义衡量算法执行时间与问题规模之间的关系衡量算法在运行过程中所占用的额外存储空间与问题规模之间的关系表达方式通常用大O符号表示,如O(n)、O(n^2&am…...

tensorRT安装详解(linux与windows)
目录 tensorRT介绍 前置准备 安装cuda与cudnn linux windows cuda版本查看 下载安装包 linux安装 安装 安装验证 windows安装 安装 环境变量配置 安装验证 tensorRT介绍 有关tensorRT的介绍见 TensorRT简介-CSDN博客 前置准备 安装cuda与cudnn linux Linux下…...
MYSQL OPTIMIZE TABLE 命令重建表和索引
在 MySQL 中,OPTIMIZE TABLE 命令用于重建表和相关索引,以及回收未使用的空间。这个命令对于维护和优化数据库表的性能非常有用,特别是在进行了大量的数据删除操作之后。OPTIMIZE TABLE 可以减少数据文件的碎片化,确保数据存储更加…...
开发指南075-各种动画效果
方法一、使用动画GIF图标 方法二、使用vue-count-to import CountTo from vue-count-to components: { CountTo }, <count-to :start-val"0" :end-val"num" :duration"num>0?num:1" class"card-panel-num" /> 方法…...
使用 el-upload 如何做到发送一次请求上传多个文件
在使用 Element UI 的 el-upload 组件时,默认情况下每次选择文件都会触发一次上传请求。如果你需要一次性上传多个文件,而不是每个文件都触发一次请求,可以通过一些配置和代码处理来实现。 方法一:通过配置file-list(…...

GEE引擎架设好之后进游戏时白屏的解决方法——gee引擎白屏修复
这两天测试GeeM2引擎的服务端,最常见的问题就是点击开始游戏出现白屏,最早还以为是服务端问题,结果是因为升级了引擎,而没有升级NewUI这份文件导致的。解决方法如下: 下载GEE引擎包最新版,(可以…...
Linux LVS 通用命令行
LVS(Linux Virtual Server)是一种基于Linux操作系统的负载均衡技术,它通过网络负载均衡技术将客户端请求分发到多台实际服务器上,以提高系统的性能和可靠性。在LVS中,常用的命令行工具主要是ipvsadm,以及一…...
laravel .env环境变量原理
介绍 对于应用程序运行的环境来说,不同的环境有不同的配置通常是很有用的。Laravel 利用 Vance Lucas 的 PHP 库 DotEnv 使得此项功能的实现变得非常简单。当应用程序收到请求时,.env 文件中列出的所有变量将被加载到 PHP 的超级全局变量 $_ENV 中。 使…...

Nuxt.js 应用中的 app:templatesGenerated 事件钩子详解
title: Nuxt.js 应用中的 app:templatesGenerated 事件钩子详解 date: 2024/10/19 updated: 2024/10/19 author: cmdragon excerpt: app:templatesGenerated 是 Nuxt.js 的一个生命周期钩子,在模板编译到虚拟文件系统(Virtual File System, VFS)之后被调用。这个钩子允许…...

新时代AI桌宠:XGO Rider让你的办公室瞬间高大上
XGO Rider Luwu 智能打造了桌面双轮足式机器人 XGO Rider,这款全球首创的轮腿式桌面AI机器人,正在悄然改变我们的办公环境。它不仅是一个高科技玩具,更是一个能大幅提升工作效率和办公室科技感的智能助手。 XGO Rider 新时代“桌宠” micr…...
matlab的resample函数
MATLAB中resample函数用法 - 知乎 (zhihu.com) 主要是经常忘记了重采样时哪个是原采样率,哪个是重采样后的采样率(目标采样率)。这里记录下,目标采样率在前面!...

idea怎么取消自动打开项目
idea设置不自动打开项目 选择File>> Settings 选择Appearance & Behavior >> System Settings 去掉勾选的Reopen last project on startup...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...

【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...

MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...

【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...

全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...

图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...