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

【Java基础笔记vlog】Java中常见的几种数组排序算法汇总详解

Java中常见的几种排序算法:

  • 冒泡排序(Bubble Sort)
  • 选择排序(Selection Sort)
  • 插入排序(Insertion Sort)
  • 希尔排序(Shell Sort)
  • 归并排序(Merge Sort)
  • 快速排序(Quick Sort)
  • 堆排序(Heap Sort)
  • 计数排序(Counting Sort)
  • 桶排序(Bucket Sort)
  • 基数排序(Radix Sort)

其中冒泡、选择、插入等是最常用的几种排序算法(必须要掌握)

算法复杂度

其中,n表示输入元素的数量,k表示元素的取值范围大小。

  • 稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
  • 不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。
  • 时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。
  • 空间复杂度:是指算法在计算机 内执行时所需存储空间的度量,它也是数据规模n的函数。

1.冒泡排序(Bubble Sort)

冒泡排序的基本思想是对比相邻的元素值,如果满足条件就交换元素值,把较小的元素移动到数组前面,把较大的元素移动到数组后面(也就是交换元素的位置),这样较小的元素就像气泡一样从底部升到顶部。

算法示例

//排序实现public void sort(int[] arry) {for(int i=1;i<arry.length;i++) {for(int j=0;j<arry.length-i;j++) {//如果数组元素第一位比第二位大 就创建temp把第一位赋值于他 //然后第二位向前移,temp存储的第一位的值到第二位上 完成一次排序if(arry[j]>arry[j+1]) {       int temp = arry[j];arry[j] = arry[j+1];arry[j+1] = temp;}}}showArry(arry);//遍历}public void showArry(int[] arry) {for(int i:arry) {System.out.print(">"+i);}}

2.选择排序(Selection Sort)

基本思想:选择排序的基本思想是每次从待排序的元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的元素排完。

public class SelectionSort {public static void sort(int[] arr) {int n = arr.length;for (int i = 0; i < n - 1; i++) {int minIndex = i;for (int j = i + 1; j < n; j++) {if (arr[j] < arr[minIndex]) {minIndex = j;}}int temp = arr[minIndex];arr[minIndex] = arr[i];arr[i] = temp;}}
}

3.插入排序(Insertion Sort)

基本思想:将未排序数据插入到已排序序列的合适位置

public class InsertionSort {public static void sort(int[] arr) {int n = arr.length;for (int i = 1; i < n; i++) {int key = arr[i];int j = i - 1;while (j >= 0 && arr[j] > key) {arr[j + 1] = arr[j];j--;}arr[j + 1] = key;}}
}

4.希尔排序(Quick Sort)

基本思想:将待排序的数组按照一定的间隔进行分组,对每组使用插入排序算法进行排序,然后缩小间隔,再对分组进行排序,直到间隔为1为止。逐渐减小间隔大小的方法有助于提高排序过程的效率,可以减少比较和交换的次数。这是希尔排序算法的一个关键特点。

算法示例:
import org.junit.jupiter.api.Assertions;
import java.util.Arrays;public class Shell {public static void shellSort(int[] arr) {int n = arr.length;// 初始化间隔(gap)的值,它决定了每次迭代中子数组的大小// 从数组长度的一半开始作为初始间隔值,gap就是分割的子数组数量for (int gap = n / 2; gap > 0; gap /= 2) {// 循环从间隔值开始,遍历数组直到数组的末尾;代表循环所有的子数组for (int i = gap; i < n; i++) {int temp = arr[i];int j = i;// 将当前元素 arr[j] 的值替换为前一个元素 arr[j - gap] 的值。// 通过这个操作,将较大的元素向后移动,为当前元素腾出位置while (j >= gap && arr[j - gap] > temp) {arr[j] = arr[j - gap];j -= gap;}arr[j] = temp;}}}public static void main(String[] args) {int[] arr = {5, 2, 8, 3, 1, 6};int[] expectedArr = {1, 2, 3, 5, 6, 8};Shell.shellSort(arr);System.out.println("arr = " + Arrays.toString(arr));Assertions.assertArrayEquals(expectedArr, arr);}
}

5.归并排序(Merge Sort)

基本思想:归并排序是一种分治思想的排序算法,它的基本思想是将待排序的数组分成若干个子序列,每个子序列都是有序的,然后再将子序列合并成一个有序的数组。
算法示例:
import org.junit.jupiter.api.Assertions;
import java.util.Arrays;public class Merge {public static void main(String[] args) {int[] arr = {5, 2, 8, 3, 1, 6};int[] expectedArr = {1, 2, 3, 5, 6, 8};Merge.mergeSort(arr, 0, arr.length - 1);System.out.println("arr = " + Arrays.toString(arr));Assertions.assertArrayEquals(expectedArr, arr);}public static void mergeSort(int[] arr, int left, int right) {if (left < right) {int mid = (left + right) / 2;mergeSort(arr, left, mid);mergeSort(arr, mid + 1, right);merge(arr, left, mid, right);}}public static void merge(int[] arr, int left, int mid, int right) {// 子数组 L 的大小int n1 = mid - left + 1;// 右子数组 R 的大小int n2 = right - mid;// 创建两个临时数组 L 和 R ,分别用来存储左子数组和右子数组的元素int[] L = new int[n1];int[] R = new int[n2];// 使用 for 循环将原始数组 arr 中的元素复制到临时数组 L 和 R 中,分别从 left 和 mid + 1 开始for (int i = 0; i < n1; i++) {L[i] = arr[left + i];}for (int j = 0; j < n2; j++) {R[j] = arr[mid + 1 + j];}// 初始化三个变量 i、j和k,分别指向数组 L 、R 和原始数组 arr 的起始位置int i = 0, j = 0, k = left;// 使用 while 循环,比较 L 和 R 的元素,并将较小的元素放回原始数组 arr 中while (i < n1 && j < n2) {if (L[i] <= R[j]) {arr[k] = L[i];i++;} else {arr[k] = R[j];j++;}k++;}// 当 L 或 R 中的元素用完时,将剩余的元素依次放回原始数组 arr 中while (i < n1) {arr[k] = L[i];i++;k++;}while (j < n2) {arr[k] = R[j];j++;k++;}// merge 方法执行完毕后,两个子数组范围内的元素已经按照从小到大的顺序合并到了原始数组 arr 中}
}

6. 快速排序(Quick Sort)

基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,然后再分别对这两部分记录继续进行排序,以达到整个序列有序的目的。
算法示例:
import org.junit.jupiter.api.Assertions;
import java.util.Arrays;public class Quick {public static void main(String[] args) {int[] arr = {5, 2, 8, 6, 1, 3};int[] expectedArr = {1, 2, 3, 5, 6, 8};Quick.quickSort(arr, 0, arr.length - 1);System.out.println("arr = " + Arrays.toString(arr));Assertions.assertArrayEquals(expectedArr, arr);}// 接收一个数组 arr,一个低索引 low ,和一个高索引 high 作为参数public static void quickSort(int[] arr, int low, int high) {// 检查 low 是否小于 high。如果不是,则意味着数组只有一个元素或为空,因此不需要排序if (low < high) {int pivot = partition(arr, low, high);quickSort(arr, low, pivot - 1);quickSort(arr, pivot + 1, high);}}/*** 取最后一个元素作为枢轴元素,将较小的元素放在左边,较大的元素放在右边* @param arr 输入数组* @param low 低位索引* @param high 高位索引* @return 枢轴所在位置*/private static int partition(int[] arr, int low, int high) {// 将最后一个元素作为枢轴元素( arr[high] )int pivot = arr[high];// 将 i 初始化为 low - 1,用于跟踪较小元素的索引int i = low - 1;for (int j = low; j < high; j++) {if (arr[j] < pivot) {// 如果当前元素 arr[j] 小于枢轴元素,则增加 i 并交换 arr[i] 和 arr[j]// 较小元素索引+1i++;// 将当前元素 arr[j] 放在较小元素索引位置// 将较小元素放在前面swap(arr, i, j);}// 其他情况,则较小元素索引没有增加,说明当前元素应该放在右边}// 将枢轴元素( arr[high] )与索引 i + 1 处的元素交换。// 确保枢轴元素左边是较小元素,右边是较大元素swap(arr, i + 1, high);// 将 i + 1 作为枢轴索引返回return i + 1;}private static void swap(int[] arr, int i, int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}
}


7. 堆排序(Heap Sort)

基本思想:将待排序的数组构建成一个大根堆(或小根堆),然后将堆顶元素与堆底元素交换位置,再将剩余元素重新构建成堆,重复执行交换和重构堆的操作,直到整个数组有序。
算法示例:
public class Heap {// 堆排序方法public static void heapSort(int[] arr) {int n = arr.length;// 构建大根堆,// 这段代码是构建大根堆的过程,它的循环次数为n/2-1次,是因为在完全二叉树中,叶子节点不需要进行堆化操作,// 所以只需要对非叶子节点进行堆化,而非叶子节点的数量为n/2-1个。因此,只需要循环n/2-1次即可完成大根堆的构建。// 非叶子节点在一维数组中就是前面 n/2-1for (int i = n / 2 - 1; i >= 0; i--) {// 从最底层的根节点开始堆化,每次执行完成后,都找出最大值,并放在根节点位置// 逐层往上找,循环结束后,第一个元素肯定是最大值heapify(arr, n, i);}// 依次取出堆顶元素,并将余下元素继续堆化,得到有序序列for (int i = n - 1; i >= 0; i--) {// 第一个for循环已经找出最大值,所以先做交货,把最大值换到最后一个位置// 把最大值交换到最后一个位置,下一次循环最后一个位置就不比较了swap(arr, 0, i);// 继续找出最大值,放在第一个位置heapify(arr, i, 0);}}private static void heapify(int[] arr, int heapSize, int i) {int largest = i; // 初始化假设最大值为根节点int left = 2 * i + 1; // 相对于索引i的左节点索引int right = 2 * i + 2; // 相对于索引i的右节点索引// 找到左右子节点中的最大值if (left < heapSize && arr[left] > arr[largest]) {// 如果有左节点,且左节点大于根节点,则记录左节点为最大值largest = left;}if (right < heapSize && arr[right] > arr[largest]) {// 如果有右节点,且右节点大于最大值,则记录右节点为最大值largest = right;}// 上面两个if之后,肯定找到最大值if (largest != i) {// i 是根节点下标// 如果最大值不是根节点,则交换根节点与最大值节点,// 并递归地对最大值节点进行堆化swap(arr, i, largest);heapify(arr, heapSize, largest);}}private static void swap(int[] arr, int i, int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}public static void main(String[] args) {int[] arr = {5, 2, 8, 3, 12, 35, 57, 1, 6};int[] expectedArr = {1, 2, 3, 5, 6, 8, 12, 35, 57};Heap.heapSort(arr);System.out.println("arr = " + Arrays.toString(arr));Assertions.assertArrayEquals(expectedArr, arr);}
}

8. 计数排序(Counting Sort)

基本思想:统计数组中每个元素出现的次数,然后根据元素出现的次数依次将元素放入有序的数组中。
算法示例:
import org.junit.jupiter.api.Assertions;
import java.util.Arrays;public class Counting {public static void countingSort(int[] arr) {int n = arr.length;// 取出数组中最大值int max = getMax(arr);int[] count = new int[max + 1];// 统计每个元素出现的次数for (int i = 0; i < n; i++) {count[arr[i]]++;}// 计算每个元素在有序序列中的位置for (int i = 1; i <= max; i++) {// 因为count包含了每个数据出现的次数,所以从小到大,// 逐个往前加得到就是原数组中每个元素在有序序列中应有的位置count[i] += count[i - 1];}// 输出有序序列int[] sortedArr = new int[n];for (int i = n - 1; i >= 0; i--) {int item = arr[i];//元素int itemPos = count[item];// 元素在有序数组中的位置sortedArr[itemPos - 1] = item; // 将元素填入有序数组count[item]--;}// 将有序序列复制回原数组System.arraycopy(sortedArr, 0, arr, 0, n);}private static int getMax(int[] arr) {int max = arr[0];for (int i = 1; i < arr.length; i++) {if (arr[i] > max) {max = arr[i];}}return max;}public static void main(String[] args) {int[] arr = {5, 2, 6, 8, 3, 1, 6, 5, 12};int[] expectedArr = {1, 2, 3, 5, 5, 6, 6, 8, 12};Counting.countingSort(arr);System.out.println("arr = " + Arrays.toString(arr));Assertions.assertArrayEquals(expectedArr, arr);}
}

9. 桶排序(Bucket Sort)

基本思想:将待排序的数组分到有限数量的桶里,然后对每个桶进行排序,最后依次将所有桶中的元素取出来,组成有序的数组。
桶排序的时间复杂度为O(n),其中n为待排序元素的个数。
算法示例:
import org.junit.jupiter.api.Assertions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;public class Bucket {public static void main(String[] args) {int[] arr = {5, 2, 8, 3, 12, 35, 57, 1, 6};int[] expectedArr = {1, 2, 3, 5, 6, 8, 12, 35, 57};Bucket.bucketSort(arr, 20);System.out.println("arr = " + Arrays.toString(arr));Assertions.assertArrayEquals(expectedArr, arr);}/*** 桶排序* @param arr 待排序数组* @param bucketSize 桶大小,数据不宜过大,桶越大,后续对桶内数据排序越耗时*/public static void bucketSort(int[] arr, int bucketSize) {if (arr.length == 0) {return;}// 循环数组,先找到最小值和最大值int minValue = arr[0];int maxValue = arr[0];for (int i = 1; i < arr.length; i++) {if (arr[i] < minValue) {minValue = arr[i];} else if (arr[i] > maxValue) {maxValue = arr[i];}}// 根据桶的大小,计算桶个数,并初始化桶int bucketCount = (maxValue - minValue) / bucketSize + 1;List<List<Integer>> buckets = new ArrayList<>(bucketCount);for (int i = 0; i < bucketCount; i++) {buckets.add(new ArrayList<>());}for (int i = 0; i < arr.length; i++) {int bucketIndex = (arr[i] - minValue) / bucketSize;buckets.get(bucketIndex).add(arr[i]);}int currentIndex = 0;for (int i = 0; i < bucketCount; i++) {List<Integer> bucket = buckets.get(i);// 对桶内数据进行排序Collections.sort(bucket);// 将数据逐个从桶内取出,并存入数组for (int j = 0; j < bucket.size(); j++) {arr[currentIndex++] = bucket.get(j);}}}}

10. 基数排序(Radix Sort)

基本思想:将待排序的数组按照位数(个位、十位、百位)进行划分,然后依次对每个位上的数字进行排序,最终得到有序的数组。

基数排序的时间复杂度为O(d(n+k)),其中d为最大元素的位数,n为待排序元素的个数,k为桶的个数。

算法示例:
public class Radix {public static void radixSort(int[] arr) {if (arr.length == 0) {return;}// 循环取得数组中的最大值int maxNum = arr[0];for (int i = 1; i < arr.length; i++) {if (arr[i] > maxNum) {maxNum = arr[i];}}// 根据最大值算出数组中的最大位数,个位、十位、百位、千位等int maxDigit = 0;while (maxNum != 0) {maxNum /= 10;maxDigit++;}// 初始化10个list,分别存放位数是0-9的10组数字List<List<Integer>> buckets = new ArrayList<>(10);for (int i = 0; i < 10; i++) {buckets.add(new ArrayList<>());}int mod = 10; // 初始10,用于数据个位数取模int div = 1; // 桶序号除数// 按位数循环数组,个位循环1次,十位循环2次,百位循环3次,以此类推!for (int i = 0; i < maxDigit; i++, mod *= 10, div *= 10) {// 循环数组,将数据分别存入桶中// 第一次循环,桶里面的个位数顺序排序完成// 第二次循环,个位、十位都排序完成// 第三次循环,个位、十位、百位都排序完成for (int j = 0; j < arr.length; j++) {// 计算当前位数的桶序号int bucketIndex = (arr[j] % mod) / div;buckets.get(bucketIndex).add(arr[j]);}// 循环桶列表,将当前位数已排序的数据放入数组中int currentIndex = 0;for (int j = 0; j < 10; j++) {List<Integer> bucket = buckets.get(j);for (int k = 0; k < bucket.size(); k++) {arr[currentIndex++] = bucket.get(k);}bucket.clear();}}}public static void main(String[] args) {int[] arr = {5, 2, 8, 3, 12, 35, 57, 1, 6};int[] expectedArr = {1, 2, 3, 5, 6, 8, 12, 35, 57};Radix.radixSort(arr);System.out.println("arr = " + Arrays.toString(arr));Assertions.assertArrayEquals(expectedArr, arr);}
}

    相关文章:

    【Java基础笔记vlog】Java中常见的几种数组排序算法汇总详解

    Java中常见的几种排序算法&#xff1a; 冒泡排序&#xff08;Bubble Sort&#xff09;选择排序&#xff08;Selection Sort&#xff09;插入排序&#xff08;Insertion Sort&#xff09;希尔排序&#xff08;Shell Sort&#xff09;归并排序&#xff08;Merge Sort&#xff09…...

    WebRTC与RTSP|RTMP的技术对比:低延迟与稳定性如何决定音视频直播的未来

    引言 音视频直播技术已经深刻影响了我们的生活方式&#xff0c;尤其是在教育、医疗、安防、娱乐等行业中&#xff0c;音视频技术成为了行业发展的重要推动力。近年来&#xff0c;WebRTC作为一种开源的实时通信技术&#xff0c;成为了音视频领域的重要选择&#xff0c;它使得浏览…...

    spring cloud alibaba Sentinel详解

    spring cloud alibaba Sentinel详解 spring cloud alibaba Sentinel介绍 Sentinel 是阿里巴巴开源的一款动态流量控制组件&#xff0c;主要用于保障微服务架构中的服务稳定性。它能够对微服务中的各种资源&#xff08;如接口、服务方法等&#xff09;进行实时监控、流量控制、…...

    Kafka + Flink + Spark 构建实时数仓全链路实战

    本文聚焦如何通过 Kafka + Flink + Spark 构建一套稳定、可扩展、可插拔的实时数仓体系。覆盖从数据接入、实时清洗、指标计算,到离线补数、数据一致性保障的完整链路设计,结合实践样例提供可复制的落地方法。 🧱 一、架构总览 ┌────────────┐│ 数据源 …...

    React19源码系列之渲染阶段performUnitOfWork

    在 React 内部实现中&#xff0c;将 render 函数分为两个阶段&#xff1a; 渲染阶段提交阶段 其中渲染阶段可以分为 beginWork 和 completeWork 两个阶段&#xff0c;而提交阶段对应着 commitWork。 在之前的root.render过程中&#xff0c;渲染过程无论是并发模式执行还是同…...

    Redis中的事务和原子性

    在 Redis 中&#xff0c;事务 和 原子性 是两个关键概念&#xff0c;用于保证多个操作的一致性和可靠性。以下是 Redisson 和 Spring Data Redis 在处理原子性操作时的区别与对比&#xff1a; 1. Redis 的原子性机制 Redis 本身通过以下方式保证原子性&#xff1a; 单线程模型…...

    怎样把B站的视频保存到本地

    在B站&#xff08;哔哩哔哩&#xff09;上&#xff0c;有数不清的优质内容&#xff0c;无论是搞笑视频、学习资料&#xff0c;还是动漫影视&#xff0c;总有一些视频让你想反复观看。但是&#xff0c;遇到没有网络或流量不够用的时候&#xff0c;怎么办&#xff1f;把B站的视频…...

    Vue3前后端分离用户信息显示方案

    在Vue3前后端分离的项目中&#xff0c;若后端仅返回用户ID&#xff0c;可通过以下步骤显示用户名&#xff1a; 解决方案 获取用户信息API 确保后端提供以下任意一种接口&#xff1a; 批量查询接口&#xff1a;传入多个用户ID&#xff0c;返回对应的用户信息列表 单个查询接口…...

    DL00987-基于深度学习YOLOv11的红外鸟类目标检测含完整数据集

    提升科研能力&#xff0c;精准识别红外鸟类目标&#xff01; 完整代码数据集见文末 针对科研人员&#xff0c;尤其是研究生们&#xff0c;是否在鸟类目标检测中遇到过数据不够精准、处理困难等问题&#xff1f;现在&#xff0c;我们为你提供一款基于深度学习YOLOv11的红外鸟类…...

    黑马程序员C++2024新版笔记 第4章 函数和结构体

    1.结构体的基本应用 结构体struct是一种用户自定义的复合数据类型&#xff0c;可以包含不同类型的成员。例如&#xff1a; struct Studet {string name;int age;string gender; } 结构体的声明定义和使用的基本语法&#xff1a; struct 结构体类型 {成员1类型 成员1名称;成…...

    数据仓库,扫描量

    有五种通用技术用于限制数据的扫描量&#xff0c;正如图3 - 4所示。第一种技术是扫描那些被打上时戳的数据。当一个应用对记录的最近一次变化或更改打上时戳时&#xff0c;数据仓库扫描就能够很有效地进行&#xff0c;因为日期不相符的数据就接触不到了。然而&#xff0c;目前的…...

    Day126 | 灵神 | 二叉树 | 层数最深的叶子结点的和

    Day126 | 灵神 | 二叉树 | 层数最深的叶子结点的和 1302.层数最深的叶子结点的和 1302. 层数最深叶子节点的和 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 这道题用层序遍历的思路比较好想&#xff0c;就把每层的都算一下&#xff0c;然后返回最后一层的和就…...

    Python实例题:人机对战初体验Python基于Pygame实现四子棋游戏

    目录 Python实例题 题目 代码实现 实现原理 游戏逻辑&#xff1a; AI 算法&#xff1a; 界面渲染&#xff1a; 关键代码解析 游戏棋盘渲染 AI 决策算法 胜利条件检查 使用说明 安装依赖&#xff1a; 运行游戏&#xff1a; 游戏操作&#xff1a; 扩展建议 增强…...

    Vue3性能优化: 大规模列表渲染解决方案

    # Vue3性能优化: 大规模列表渲染解决方案 一、背景与挑战 背景 在大规模应用中&#xff0c;Vue3的列表渲染性能一直是开发者关注的焦点。大规模列表渲染往往会导致卡顿、内存占用过高等问题&#xff0c;影响用户体验和系统整体性能。 挑战 渲染大规模列表时&#xff0c;DOM操作…...

    笔记:将一个文件服务器上的文件(一个返回文件数据的url)作为另一个http接口的请求参数

    笔记&#xff1a;将一个文件服务器上的文件&#xff08;一个返回文件数据的url&#xff09;作为另一个http接口的请求参数 最近有这么个需求&#xff0c;需要往某一个业务的外部接口上传文件信息&#xff0c;但是现在没有现成的文件&#xff0c;只在数据库存了对应的url&#…...

    【RocketMQ 生产者和消费者】- 生产者启动源码 - MQClientInstance 定时任务(4)

    文章目录 1. 前言2. startScheduledTask 启动定时任务2.1 fetchNameServerAddr 拉取名称服务地址2.2 updateTopicRouteInfoFromNameServer 更新 topic 路由信息2.2.1 topic 路由信息2.2.2 updateTopicRouteInfoFromNameServer 获取 topic2.2.3 updateTopicRouteInfoFromNameSer…...

    超全GPT-4o 风格提示词案例,持续更新中,附使用方式

    本文汇集了各类4o风格提示词的精选案例&#xff0c;从基础指令到复杂任务&#xff0c;从创意写作到专业领域&#xff0c;为您提供全方位的参考和灵感。我们将持续更新这份案例集&#xff0c;确保您始终能够获取最新、最有效的提示词技巧。 让我们一起探索如何通过精心设计的提…...

    Android 自定义SnackBar和下滑取消

    如何自定义SnackBar 首先我们得了解SnackBar的布局&#xff1a; 之前我看有一些方案是获取内部的contentLayout&#xff0c;然后做一些处理。但是现在已经行不通了&#xff1a; RestrictTo(LIBRARY_GROUP) public static final class SnackbarLayout extends BaseTransientB…...

    Netty学习专栏(三):Netty重要组件详解(Future、ByteBuf、Bootstrap)

    文章目录 前言一、Future & Promise&#xff1a;异步编程的救星1.1 传统NIO的问题1.2 Netty的解决方案1.3 代码示例&#xff1a;链式异步操作 二、ByteBuf&#xff1a;重新定义数据缓冲区2.1 传统NIO ByteBuffer的缺陷2.2 Netty ByteBuf的解决方案2.3 代码示例&#xff1a;…...

    详解 C# 中基于发布-订阅模式的 Messenger 消息传递机制:Messenger.Default.Send/Register

    &#x1f9d1; 博主简介&#xff1a;CSDN博客专家、CSDN平台优质创作者&#xff0c;高级开发工程师&#xff0c;数学专业&#xff0c;10年以上C/C, C#, Java等多种编程语言开发经验&#xff0c;拥有高级工程师证书&#xff1b;擅长C/C、C#等开发语言&#xff0c;熟悉Java常用开…...

    多场景游戏AI新突破!Divide-Fuse-Conquer如何激发大模型“顿悟时刻“?

    多场景游戏AI新突破&#xff01;Divide-Fuse-Conquer如何激发大模型"顿悟时刻"&#xff1f; 大语言模型在强化学习中偶现的"顿悟时刻"引人关注&#xff0c;但多场景游戏中训练不稳定、泛化能力差等问题亟待解决。Divide-Fuse-Conquer方法&#xff0c;通过…...

    Java 函数式接口(Functional Interface)

    一、理论说明 1. 函数式接口的定义 Java 函数式接口是一种特殊的接口&#xff0c;它只包含一个抽象方法&#xff08;Single Abstract Method, SAM&#xff09;&#xff0c;但可以包含多个默认方法或静态方法。函数式接口是 Java 8 引入 Lambda 表达式的基础&#xff0c;通过函…...

    分布式锁总结

    文章目录 分布式锁什么是分布式锁&#xff1f;分布式锁的实现方式基于数据库(mysql)实现基于缓存(redis)多实例并发访问问题演示项目代码(使用redis)配置nginx.confjmeter压测复现问题并发是1&#xff0c;即不产生并发问题并发30测试,产生并发问题(虽然单实例是synchronized&am…...

    使用MybatisPlus实现sql日志打印优化

    背景&#xff1a; 在排查无忧行后台服务日志时&#xff0c;一个请求可能会包含多个执行的sql&#xff0c;经常会遇到SQL语句与对应参数不连续显示&#xff0c;或者参数较多需要逐个匹配的情况。这种情况下&#xff0c;如果需要还原完整SQL语句就会比较耗时。因此&#xff0c;我…...

    springboot中redis的事务的研究

    redis的事务类似于队列操作&#xff0c;执行过程分为三步&#xff1a; 开启事务入队操作执行事务 使用到的几个命令如下&#xff1a; 命令说明multi开启一个事务exec事务提交discard事务回滚watch监听key(s)&#xff1a;当监听一个key(s)时&#xff0c;如果在本次事务提交之…...

    为什么我输入对了密码,还是不能用 su 切换到 root?

    “为什么我输入对了密码&#xff0c;还是不能用 su 切换到 root&#xff1f;” 其实这背后可能不是“密码错了”&#xff0c;而是系统不允许你用 su 切 root&#xff0c;即使密码对了。 &#x1f447; 以下是最常见的几个真正原因&#xff1a; ❌ 1. Root 用户没有设置密码&…...

    client.chat.completions.create方法参数详解

    response client.chat.completions.create(model"gpt-3.5-turbo", # 必需参数messages[], # 必需参数temperature1.0, # 可选参数max_tokensNone, # 可选参数top_p1.0, # 可选参数frequency_penalty0.0, # 可选参数presenc…...

    量子计算与云计算的融合:技术前沿与应用前景

    目录 引言 量子计算基础 量子计算的基本原理 量子计算的优势与挑战 量子计算的发展阶段 云计算基础 云计算的基本概念 云计算的应用领域 云计算面临的挑战 量子计算与云计算的结合 量子云计算的概念与架构 量子云计算的服务模式 量子云计算的优势 量子云计算的发展…...

    《企业级日志该怎么打?Java日志规范、分层设计与埋点实践》

    大家好呀&#xff01;&#x1f44b; 今天我们要聊一个Java开发中超级重要但又经常被忽视的话题——日志系统&#xff01;&#x1f4dd; 不管你是刚入门的小白&#xff0c;还是工作多年的老司机&#xff0c;日志都是我们每天都要打交道的"好朋友"。那么&#xff0c;如…...

    python模块管理环境变量

    概要 在 Python 应用中&#xff0c;为了将配置信息与代码分离、增强安全性并支持多环境&#xff08;开发、测试、生产&#xff09;运行&#xff0c;使用专门的模块来管理环境变量是最佳实践。常见工具包括&#xff1a; 标准库 os.environ&#xff1a;直接读取操作系统环境变量…...