当前位置: 首页 > news >正文

Java中处理千万级数据的最佳实践:性能优化指南

在今天的数字化时代,处理大规模数据已经成为许多Java应用程序的核心任务。无论您是构建数据分析工具、实现实时监控系统,还是处理大规模日志文件,性能优化都是确保应用程序能够高效运行的关键因素。本指南将介绍一系列最佳实践,帮助您在处理千万级数据时提高Java应用程序的性能。

引言

数据规模的挑战

在当今数字化时代,数据规模迅速增长。处理千万级甚至更大规模的数据集已成为常态。这些大数据集可能包含来自传感器、社交媒体、日志文件等各种来源的信息,对于企业和科研机构来说都具有重要价值。

为什么性能优化很重要

处理大规模数据时,性能问题可能导致应用程序变得缓慢或不稳定。用户体验下降,系统响应时间延长,甚至可能导致服务中断。因此,性能优化是确保应用程序能够处理大规模数据并保持高效运行的关键因素。

选择合适的数据结构

Java提供了丰富的数据结构,选择合适的数据结构对性能至关重要。

数组 vs. 列表 vs. 集合

  • 数组是最基本的数据结构之一,具有快速的随机访问能力。如果数据集的大小是已知且不变的,数组可以是一个高效的选择。然而,数组的大小是固定的,不能动态增长,这限制了其在某些场景的适用性。
  • 列表(如ArrayList)是可变大小的数据结构,适用于大部分情况。它通过动态增长内部数组的方式来处理数据。但要注意在大规模数据集上频繁添加和删除元素可能会导致性能下降,因为需要重新分配和复制数组。
  • 集合(如HashSetTreeSet)提供了快速的查找操作。选择合适的集合类型取决于您的需求。例如,HashSet对于快速查找唯一值非常有用,而TreeSet可以保持元素的有序性。

使用哈希表和树结构

  • 哈希表(如HashMap)对于快速查找和插入操作非常高效。它通过将键映射到桶中的索引来实现快速查找。
  • 树结构(如TreeMap)可以保持有序性,适用于需要有序遍历数据的情况。它基于二叉搜索树实现,因此查找操作的复杂度较低。

自定义数据结构的考虑

根据应用程序的特性,有时自定义数据结构可以提供更好的性能。例如,如果您需要高效存储大量的布尔值数据,可以考虑使用位集合(BitSet),它可以显著减小内存消耗。

import java.util.BitSet;public class BitSetExample {public static void main(String[] args) {int dataSize = 10000000;BitSet bitSet = new BitSet(dataSize);// 设置某些位为truebitSet.set(1);bitSet.set(100);bitSet.set(1000);// 检查位的状态boolean isSet = bitSet.get(100);  // 返回trueboolean isNotSet = bitSet.get(500); // 返回false}
}

在上述示例中,BitSet被用于高效地存储大量布尔值数据。

内存管理和优化

内存管理是性能优化的关键部分。不正确的内存使用可能导致内存泄漏和性能下降。

内存泄漏的检测和解决

使用工具如Java虚拟机自带的内存分析器(VisualVM)来检测潜在的内存泄漏问题。内存泄漏通常发生在对象被引用后没有被正确释放的情况下。确保及时解决这些问题,以释放未使用的内存。

public class MemoryLeakExample {private static List<Object> memoryLeakList = new ArrayList<>();public static void main(String[] args) {for (int i = 0; i < 10000000; i++) {Object obj = new Object();memoryLeakList.add(obj);}}
}

在上述示例中,未正确释放memoryLeakList中的对象可能导致内存泄漏。

使用对象池

对象池是一种重用对象的机制,它可以减少对象的频繁创建和销毁,从而提高性能。通过重复使用对象,

可以避免频繁的垃圾回收操作。常见的对象池库包括Apache Commons Pool和Google Guava。

import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;public class ObjectPoolExample {public static void main(String[] args) {GenericObjectPoolConfig<MyObject> config = new GenericObjectPoolConfig<>();config.setMaxTotal(100); // 池中最多存放的对象数量GenericObjectPool<MyObject> objectPool = new GenericObjectPool<>(new MyObjectFactory(), config);// 从对象池中获取对象MyObject obj = objectPool.borrowObject();// 使用对象// 将对象归还给对象池objectPool.returnObject(obj);}
}

在上述示例中,我们使用Apache Commons Pool创建了一个对象池,可以重复使用MyObject对象。

减少对象创建

对象的创建和销毁操作通常是性能的瓶颈之一。尽量减少不必要的对象创建,可以通过对象池、缓存等方式来实现。如果一个对象是一次性的,并且在短时间内被多次创建和销毁,考虑将其重用以减少开销。

public class ObjectCreationExample {public static void main(String[] args) {for (int i = 0; i < 10000000; i++) {// 避免在循环内创建对象String str = "Object " + i;// 使用str}}
}

在上述示例中,避免在循环内部创建大量的String对象可以提高性能。

使用弱引用和软引用

Java提供了弱引用(WeakReference)和软引用(SoftReference)来管理对象的生命周期。它们可以用于缓存和缓存清理,从而更好地管理内存。弱引用的对象在下一次垃圾回收时会被释放,而软引用的对象则会在内存不足时才被释放。

import java.lang.ref.WeakReference;public class ReferenceExample {public static void main(String[] args) {Object obj = new Object();WeakReference<Object> weakReference = new WeakReference<>(obj);// 在需要时,可以通过弱引用获取对象Object retrievedObj = weakReference.get();// 如果对象被回收,则retrievedObj将为null}
}

在上述示例中,使用弱引用可以更灵活地管理对象的生命周期。

多线程并发处理

多线程可以有效地利用多核处理器,提高数据处理速度,但也需要谨慎处理以避免竞态条件和死锁。

并发编程基础

了解多线程编程的基本原理和概念,包括线程的创建、同步和互斥。确保您的代码在多线程环境下是线程安全的。

public class ThreadSafetyExample {private static int counter = 0;public static synchronized void increment() {counter++;}public static void main(String[] args) {Thread thread1 = new Thread(() -> {for (int i = 0; i < 1000000; i++) {increment();}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 1000000; i++) {increment();}});thread1.start();thread2.start();try {thread1.join();thread2.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Counter: " + counter);}
}

在上述示例中,我们使用synchronized关键字确保increment方法的原子性,避免了竞态条件。

使用线程池

线程池是管理线程的最佳方式之一。它可以管理线程的生命周期,提供线程的复用和管理,从而减少线程创建销毁的开销。Java提供了java.util.concurrent.Executor框架来帮助您轻松创建和管理线程池。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolExample {public static void main(String[] args) {int numberOfThreads = 4;ExecutorService executorService = Executors.newFixedThreadPool(numberOfThreads);for (int i = 0; i < 10; i++) {executorService.submit(() -> {// 执行任务});}// 关闭线程池executorService.shutdown();}
}

在上述示例中,我们使用线程池管理并发任务的执行。

避免共享数据的竞态条件

在多线程环境中,多个线程可能会同时访问和修改共享数据,导致竞态条件。使用合适的锁机制(如Synchronized关键字和java.util.concurrent包中的锁)来避免这种情况。并发集合(如ConcurrentHashMap)也提供了一种线程安全的方式来处理共享数据。

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;public class ConcurrentHashMapExample {public static void main(String[] args) {Map<String, Integer> concurrentMap = new ConcurrentHashMap<>();concurrentMap.put("key1", 1);concurrentMap.put("key2", 2);// 使用并发集合进行安全的操作int value = concurrentMap.get("key1");System.out.println("Value: " + value);}
}

在上述示例中,我们使用ConcurrentHashMap来安全地操作共享数据。

使用并发集合

Java提供了各种并发集合,如ConcurrentHashMapConcurrentLinkedQueue,可以安全地在多线程环境下使用。这些集合实现了内部同步,因此可以避免手动加锁。

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;public class ConcurrentCollectionExample {public static voidmain(String[] args) {Queue<String> concurrentQueue = new ConcurrentLinkedQueue<>();concurrentQueue.offer("Item 1");concurrentQueue.offer("Item 2");// 使用并发队列进行安全的操作String item = concurrentQueue.poll();System.out.println("Item: " + item);}
}

在上述示例中,我们使用ConcurrentLinkedQueue来安全地操作队列。

锁的选择和性能影响

了解锁的种类,包括悲观锁和乐观锁,并选择合适的锁对性能的影响。例如,悲观锁(如ReentrantLock)提供了强大的互斥保护,但可能会导致线程争用,影响性能。乐观锁(如Atomic类)通过版本控制来避免争用,适用于某些高并发场景。

import java.util.concurrent.atomic.AtomicInteger;public class AtomicExample {private static AtomicInteger counter = new AtomicInteger(0);public static void main(String[] args) {counter.incrementAndGet();int value = counter.get();System.out.println("Counter: " + value);}
}

在上述示例中,我们使用AtomicInteger来实现无锁的原子操作。

数据分区和分片

将数据分为多个分区或分片可以有效提高数据处理性能。

数据分区的概念

数据分区是将数据集划分为多个较小部分的过程。每个分区都是相对独立的,可以被独立处理。数据分区的目标是将工作负载均衡地分布到不同的处理单元上,从而提高并行处理性能。

分布式计算和MapReduce

在分布式环境中使用MapReduce等技术来处理大规模数据集。MapReduce模型将数据分为多个块,然后对每个块执行Map和Reduce操作,以实现并行处理。

分片处理技术

使用分片技术将数据集分割成多个片段(或分片),每个分片可以在独立的线程或处理单元上处理。这种方式可提高数据处理的并行性,从而加速整体处理速度。分片处理适用于需要逐一处理大量数据记录的任务。

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class DataShardingExample {public static void main(String[] args) {List<DataChunk> dataChunks = loadDataChunks();ExecutorService executorService = Executors.newFixedThreadPool(4);for (DataChunk chunk : dataChunks) {executorService.submit(() -> {// 处理数据分片});}// 关闭线程池executorService.shutdown();}private static List<DataChunk> loadDataChunks() {// 加载数据分片return null;}private static class DataChunk {// 数据分片的定义}
}

在上述示例中,我们使用分片处理技术来并行处理数据分片。

索引和查询优化

如果您的应用程序涉及数据库或搜索操作,优化索引和查询是至关重要的。

数据库索引的作用

数据库索引是一种数据结构,用于加速查询操作。它们允许数据库引擎更快地查找符合特定条件的数据行。索引通常是根据表中的一个或多个列创建的。

内存中索引 vs. 磁盘索引

将索引保留在内存中可以显著提高查询性能。因为内存操作通常比磁盘访问快得多,所以将索引数据加载到内存中可以加速查询操作。此外,使用合适的数据结构来表示索引也很重要。

查询优化技巧

优化SQL查询以减少查询时间是数据库性能优化的核心。以下是一些查询优化的技巧:

  • 选择合适的索引:根据查询的条件选择适当的索引,避免全表扫描。
  • 避免不必要的连接:尽量减少查询中的连接操作。
  • 使用合适的数据类型:选择适当的数据类型来存储数据,避免数据类型转换。
  • 查询分页:如果应用程序需要分页查询结果,使用LIMIT和OFFSET来限制结果集的大小。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class QueryOptimizationExample {public static void main(String[] args) {String url = "jdbc:mysql://localhost:3306/mydatabase";String username = "user";String password = "password";try (Connection connection = DriverManager.getConnection(url, username, password)) {String sql = "SELECT * FROM mytable WHERE column1 = ? LIMIT ? OFFSET ?";try (PreparedStatement statement = connection.prepareStatement(sql)) {statement.setString(1, "value");statement.setInt(2, 10);statement.setInt(3, 0);try (ResultSet resultSet = statement.executeQuery()) {while (resultSet.next()) {// 处理查询结果}}}} catch (SQLException e) {e.printStackTrace();}}
}

在上述示例中,我们使用了查询优化技巧,包括使用索引、限制结果集大小等。

I/O操作优化

如果应用程序需要进行大量的I/O操作,如文件读写,优化这些操作也是关键。

文件读写性能优化

文件读写操作通常涉及到磁盘访问,因此可以成为性能瓶颈。以下是一些文件读写性能优化的技巧:

  • 使用缓冲:缓冲可以减少频繁的磁盘访问,提高I/O性能。Java提供了BufferedReaderBufferedWriter等类来帮助您实现缓冲。

异步I/O:如果应用程序支持异步操作,可以考虑使用异步I/O来提高并发性。

  • 文件通道:Java的NIO包提供了文件通道(FileChannel)来进行高效的文件读写操作。
  • 内存映射文件:通过内存映射文件(Memory-Mapped Files)可以将文件映射到内存中,以加速读写操作。
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;public class FileIOOptimizationExample {public static void main(String[] args) throws IOException {String filePath = "data.txt";try (RandomAccessFile file = new RandomAccessFile(filePath, "rw");FileChannel channel = file.getChannel()) {MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, file.length());// 使用内存映射文件进行读写操作buffer.force(); // 强制刷新到磁盘}}
}

在上述示例中,我们使用内存映射文件来进行高效的文件读写操作。

数据编码和序列化

数据的编码方式和序列化方式对性能有重要影响。选择合适的编码和序列化方式可以减少数据传输的开销。

数据编码方式

数据的编码方式决定了数据在传输和存储时所占用的空间。例如,对于文本数据,UTF-8编码通常是一个不错的选择,因为它可以在节省空间的同时支持多种字符。

序列化和反序列化的性能考虑

序列化是将对象转换为字节流的过程,而反序列化是将字节流还原为对象的过程。不同的序列化框架和格式对性能有不同的影响。在选择序列化方法时,需要考虑性能因素。一些常见的Java序列化框架包括Java序列化、JSON、Protocol Buffers和Avro。

使用二进制协议

在网络通信中,使用二进制协议可以减少数据传输的开销,提高性能。与文本协议相比,二进制协议通常更紧凑且更快速。

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;public class BinaryProtocolExample {public static void main(String[] args) throws IOException {// 创建一个二进制数据流ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream);// 写入数据dataOutputStream.writeInt(42);dataOutputStream.writeDouble(3.14);// 获取二进制数据byte[] binaryData = byteArrayOutputStream.toByteArray();// 处理二进制数据// ...dataOutputStream.close();}
}

在上述示例中,我们使用二进制数据流来编码数据,以提高数据传输的效率。

编程技巧和工具

一些编程技巧和工具可以帮助您更轻松地进行性能优化。

编程最佳实践

遵循Java编程的最佳实践,如避免过度的方法调用、减少不必要的异常处理、使用final关键字来优化不可变对象等。这些最佳实践有助于改善代码的可维护性和性能。

使用性能分析工具

性能分析工具可以帮助您识别应用程序中的性能瓶颈。一些常用的性能分析工具包括VisualVM、YourKit和Java Flight Recorder。通过使用这些工具,您可以查看方法调用栈、内存使用情况和线程活动,以找出性能问题的根本原因。

配置和部署优化

优化应用程序的配置和部署设置对性能也具有重要影响。在部署应用程序时,可以考虑以下一些优化策略:

  • 调整JVM参数:根据应用程序的需求,调整Java虚拟机的参数,如堆大小、垃圾回收策略和线程池大小。
  • 服务器硬件升级:如果应用程序需要更多的计算资源,可以考虑升级服务器硬件,如CPU、内存和存储设备。
  • 负载均衡:如果应用程序需要处理大量请求,可以考虑使用负载均衡器来均匀分配流量到多个服务器实例上。

监控和调试

设置监控系统来实时监视应用程序的性能,以便快速定位和解决问题。监控系统可以捕获关键性能指标,如响应时间、吞吐量和错误率。当性能问题发生时,监控数据可以帮助您快速定位问题的根本原因,并采取相应的措施来解决它们。

最佳实践示例

通过实际案例分析,展示性能优化的成果,说明如何将这些最佳实践应用到实际项目中。以下是一些可能的最佳实践示例:

  • 数据库查询优化:通过优化数据库查询语句和索引设计,将查询时间从数秒缩短到数毫秒,提高了应用程序的响应速度。
  • 并发处理优化:通过引入线程池和缓存机制,将并发请求的处理时间从几分钟降低到几秒,提高了系统的吞吐量。
  • 内存管理和垃圾回收:通过修复内存泄漏问题,减少了应用程序的内存占用,提高了稳定性和可伸缩性。

结论

处理千万级数据是一项挑战性的任务,但通过选择合适的数据结构、内存管理、多线程并发处理、数据分区、索引和查询优化、I/O操作优化、数据编码和序列化以及一些编程技巧和工具,您可以显著提高Java应用程序的性能。本指南提供了一系列最佳实践和示例,帮助您优化应用程序,确保它在处理大规模数据时表现出色。通过不断学习和优化,您可以打造出高性能的Java应用程序,满足用户和业务需求。祝您的编程之路顺利!

相关文章:

Java中处理千万级数据的最佳实践:性能优化指南

在今天的数字化时代&#xff0c;处理大规模数据已经成为许多Java应用程序的核心任务。无论您是构建数据分析工具、实现实时监控系统&#xff0c;还是处理大规模日志文件&#xff0c;性能优化都是确保应用程序能够高效运行的关键因素。本指南将介绍一系列最佳实践&#xff0c;帮…...

LCR 069.山峰数组的峰顶索引

​​题目来源&#xff1a; leetcode题目&#xff0c;网址&#xff1a;LCR 069. 山脉数组的峰顶索引 - 力扣&#xff08;LeetCode&#xff09; 解题思路&#xff1a; 二分查找即可。 解题代码&#xff1a; class Solution {public int peakIndexInMountainArray(int[] arr) {…...

AtCoder Beginner Contest 233 (A-Ex)

A.根据题意模拟即可 B.根据题意模拟即可 C.直接用map 进行dp即可 D.用前缀和进行模拟&#xff0c;用map统计前缀和&#xff0c;每次计算当前前缀和-k的个数就是以当前点为右端点答案。 E - Σ[k0..10^100]floor(X&#xff0f;10^k) (atcoder.jp) &#xff08;1&#xff09;…...

解决caffe中的python环境安装的问题

由于caffe&#xff08;GitHub - BVLC/caffe: Caffe: a fast open framework for deep learning.&#xff09;使用的python版本是2.7&#xff0c;而非python3&#xff0c;所以安装的时候使用命令&#xff1a;sudo apt install python2.7进行安装。 而在安装python的各种包时&am…...

专业图像处理软件DxO PhotoLab 7 mac中文特点和功能

DxO PhotoLab 7 mac是一款专业的图像处理软件&#xff0c;它为摄影师和摄影爱好者提供了强大而全面的照片处理和编辑功能。 DxO PhotoLab 7 mac软件特点和功能 强大的RAW和JPEG格式处理能力&#xff1a;DxO PhotoLab 7可以处理来自各种相机的RAW格式图像&#xff0c;包括佳能、…...

面试题:Kafka 为什么会丢消息?

文章目录 1、如何知道有消息丢失&#xff1f;2、哪些环节可能丢消息&#xff1f;3、如何确保消息不丢失&#xff1f; 引入 MQ 消息中间件最直接的目的&#xff1a;系统解耦以及流量控制&#xff08;削峰填谷&#xff09; 系统解耦&#xff1a; 上下游系统之间的通信相互依赖&a…...

WSL安装异常:WslRegisterDistribution failed with error: 0xc03a001a

简介&#xff1a;如果文件夹右上角是否都有两个相对的蓝色箭头&#xff0c;在进行安装wsl时&#xff0c;设置就会抛出 Installing WslRegisterDistribution failed with error: 0xc03a001a的异常 历史攻略&#xff1a; 卸载WSL WSL&#xff1a;运行Linux文件 WSL&#xff1…...

【C语言 模拟实现strcmp函数】

C语言程序设计笔记---025 C语言之模拟实现strcmp函数1、介绍strcmp函数2、模拟实现strcmp函数3、结语 C语言之模拟实现strcmp函数 前言&#xff1a; 通过C语言字符串函数的知识&#xff0c;这篇将对strcmp函数进行深入学习底层原理的知识&#xff0c;并模拟实现对应功能。 /知…...

maven 依赖版本冲突异常

maven 依赖版本冲突异常 好巧不巧&#xff0c;前几天刚刚复习完 maven 的内容今天就碰到 maven 报错。 起因是这样的&#xff0c;项目马上快要上线了&#xff0c;在上线之前需要跑一些 audit 去检查项目是否安全&#xff08;这里主要是 outdated 的依赖检查&#xff09;。总体…...

蓝牙核心规范(V5.4)11.5-LE Audio 笔记之Context Type

专栏汇总网址:蓝牙篇之蓝牙核心规范学习笔记(V5.4)汇总_蓝牙核心规范中文版_心跳包的博客-CSDN博客 爬虫网站无德,任何非CSDN看到的这篇文章都是盗版网站,你也看不全。认准原始网址。!!! 蓝牙中的上下文类型(Context Type)是用于描述音频流当前使用情况或相关使用情…...

【Linux】RPM包使用详解

&#x1f341; 博主 "开着拖拉机回家"带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——&#x1f390;开着拖拉机回家_大数据运维-CSDN博客 &#x1f390;✨&#x1f341; &#x1fa81;&#x1f341; 希望本文能够给您带来一定的帮助&#x1f338;文…...

勒索病毒最新变种.Elbie勒索病毒来袭,如何恢复受感染的数据?

引言&#xff1a; 网络犯罪正变得越来越隐秘和危险。其中&#xff0c;.Elbie勒索病毒作为数字犯罪的一部分&#xff0c;以其阴险和复杂性而备受关注。本文将带您深入探索.Elbie勒索病毒的工作原理和如何应对这一数字迷宫。如果受感染的数据确实有恢复的价值与必要性&#xff0…...

ArduPilot开源飞控之AP_Mission

ArduPilot开源飞控之AP_Mission 1. 源由2. AP_Mission类3 简令结构3.1 导航相关3.1.1 jump command3.1.2 condition delay command3.1.3 condition distance command3.1.4 condition yaw command3.1.5 change speed command3.1.6 nav guided command3.1.7 do VTOL transition3.…...

JVM111

JVM1 字节码与多语言混合编程 字节码 我们平时说的java字节码&#xff0c; 指的是用java语言编译成的字节码。准确的说任何能在jvm平台上执行的字节码格式都是一样的。所以应该统称为:jvm字节码。不同的编译器&#xff0c;可以编译出相同的字节码文件&#xff0c;字节码文件…...

排序篇(三)----交换排序

排序篇(三)----交换排序 1.冒泡排序 基本思想: ​ 通过不断地比较相邻的元素&#xff0c;将较大的元素往后移动&#xff0c;从而实现排序的目的。 具体的步骤如下&#xff1a; 从待排序的数组中选择相邻的两个元素进行比较&#xff0c;如果前一个元素大于后一个元素&#…...

React antd Table点击下一页后selectedRows丢失之前页选择内容的问题

一、问题 使用了React antd 的<Table>标签&#xff0c;是这样记录选中的行id与行内容的&#xff1a; <TabledataSource{data.list}rowSelection{{selectedRowKeys: selectedIdsInSearchTab,onChange: this.onSelectChange,}} // 表格是否可复选&#xff0c;加 type: …...

蓝牙核心规范(V5.4)11.4-LE Audio 笔记之音频模型

专栏汇总网址:蓝牙篇之蓝牙核心规范学习笔记(V5.4)汇总_蓝牙核心规范中文版_心跳包的博客-CSDN博客 爬虫网站无德,任何非CSDN看到的这篇文章都是盗版网站,你也看不全。认准原始网址。!!! 从一开始,蓝牙低功耗(Bluetooth Low Energy,BLE)音频的开发就秉持着“以设…...

Spring Boot:利用JPA进行数据库的查删

目录标题 DAO 、Service 、 Controller 层控制器文件示例代码-单个查找查找成功示例代码-列表查找查找成功示例代码-删除删除成功 DAO 、Service 、 Controller 层 DAO 层负责数据库访问&#xff0c;它封装了对数据库的访问操作&#xff0c;例如查询、插入、更新和删除等。 Q…...

1711: 【穷举】满足条件的整数

题目描述 假设a、b、c均为整数&#xff08;1<a,b,c<100)&#xff0c;同时a<b&#xff0c;找出所有符合条件&#xff1a;a2 b2 n*c3的整数组。 按a从小到大的顺序输出所有满足条件的整数组&#xff08;若a相同&#xff0c;则按b从小到大的顺序输出&#xff09; 输入…...

【数据结构】堆的应用-----TopK问题

目录 一、前言 二、Top-k问题 &#x1f4a6;解法一&#xff1a;暴力排序 &#x1f4a6;解法二&#xff1a;建立N个数的堆 &#x1f4a6;解法三&#xff1a;建立K个数的堆&#xff08;最优解&#xff09; 三、完整代码和视图 四、共勉 一、前言 在之前的文章中&#xff…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

ServerTrust 并非唯一

NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

Element Plus 表单(el-form)中关于正整数输入的校验规则

目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入&#xff08;联动&#xff09;2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

OPENCV形态学基础之二腐蚀

一.腐蚀的原理 (图1) 数学表达式&#xff1a;dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一&#xff0c;腐蚀跟膨胀属于反向操作&#xff0c;膨胀是把图像图像变大&#xff0c;而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...