java基础 数组Array的介绍

news2025/4/15 23:05:28

Array

  • 数组定义
  • 一维数组
  • 多维数组
  • 动态数组
  • 常见方法
    • Arrays
      • 排序
        • 1.sort() 排序
        • 2.parallelSort() 排序
      • 查找:binarySearch()
      • 填充:fill()
      • 比较:equals() 和 deepEquals()
      • 复制:copyOf() 和 copyOfRange()
      • 转换为列表:asList()
      • 转换为字符串:toString() 和 deepToString()
      • 流操作:stream()
      • Arrays总结
    • ArrayUtils

数组定义

数组(Array)是一种线性数据结构,用于存储相同类型元素的集合。元素通过索引(下标)访问,索引通常从 0 开始

一维数组

(1) 初始化
静态初始化:直接指定元素值。

int[] arr = {1, 2, 3}; // 这两种一样 可以简化new int[]
int[] arr = new int[]{1, 2, 3}; 

动态初始化:指定长度,填充默认值(如 0、null)。

int[] arr = new int[5]; // Java

两者区别主要在于元素是否确定下来,但初始容量的大小已经固定了

(2) 访问元素
元素通过**索引(下标)**访问获取操作,如 int[] is = { 5, 8, 3, 12, 24, 30, 18, 1, 10, 13 };
数组的位置这index起始为0 对应数组元素
在这里插入图片描述
代码示例如下

int value = arr[0]; // 获取第一个元素
arr[1] = 10;        // 修改第二个元素

(3) 遍历数组

for (int i = 0; i < arr.length; i++) {
    System.out.println(arr[i]); // 按索引遍历
}

for (int num : arr) {
    System.out.println(num);    // 增强for循环(Java)
}

(4) 插入元素
尾部插入:直接赋值(若空间足够)。
中间插入:需将后续元素后移。

// 在索引2处插入元素99
for (int i = arr.length-1; i > 2; i--) {
    arr[i] = arr[i-1]; // 后移元素
}
arr[2] = 99;

(5) 删除元素
中间删除:需将后续元素前移。

// 删除索引2处的元素
for (int i = 2; i < arr.length-1; i++) {
    arr[i] = arr[i+1]; // 前移元素
}
arr[arr.length-1] = 0; // 末尾置空(可选)

多维数组

数组的元素也可以是数组,形成多维结构(如二维数组表示矩阵):

// Java二维数组
int[][] matrix = {
    {1, 2, 3},
    {4, 5, 6}
};
System.out.println(matrix[1][2]); // 输出6

这种方式常见的是在 IO流的拷贝操作中

    public void copyTest02(){
        try(FileReader fileReader = new FileReader("fileWriteTest.txt");
            FileWriter fileWriter = new FileWriter("D:\\duxx\\fileWriteTestCopy.txt")){
            char[] chars = new char[1024*1024];// 2MB
            int readLen;
            while ((readLen = fileReader.read(chars)) != -1){
                fileWriter.write(chars,0,readLen);
            }
            fileWriter.flush();
            System.out.println("管道刷新成功~");
        }catch (IOException e){
            e.printStackTrace();
        }
    }

char[] chars = new char[1024*1024];解释:定义一个1024长度的数组,每个元素是一个1024长度的char类型数组,所以元素总数量:1024×1024 = 1,048,576,在Java中char是16位的Unicode字符,占用2个字节。所以该数组总字节是2,097,152字节,1MB(兆字节)等于1024KB(千字节),而1KB等于1024B(字节)
1MB(兆字节) = 1,048,576字节(即 1024×1024)。
2,097,152字节 = 2,097,152 ÷ 1,048,576 = 2MB
因此:用在上面例子中,即每次拷贝已2兆的大小转移

byte[] byters = new byte[1024*1024]。byte占用1个字节。这个是分配大约1MB的内存空间来存储字符数据

动态数组

为解决静态数组长度固定的问题,引入动态数组,Java 的 ArrayList,ArrayList是基于数组实现的动态数组,自动扩容:当容量不足时,按比例(如翻倍)扩展内存。其实现的机制原理是如下示例

步骤1:初始无参构造:数组为空

	// 创建ArrayList
    ArrayList<String> str= new ArrayList<String>();

源码底层实现逻辑,创建一个

	// 调用初始化无参构造方法。创建一个空数组elementData 并赋以 初始默认容量数组
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
    //定义一个元素数据 这样一个初始数组
    transient Object[] elementData; 
	//ArrayList定义的静态常量空数组 DEFAULTCAPACITY_EMPTY_ELEMENTDATA
	private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

arrayList 没有提供查看容量大小方法,我们通过反射方式看下容量大小,即elementData长度

    @Test
    public void testQ() throws NoSuchFieldException, IllegalAccessException {
        //可以在这里的构造函数来进行ArrayList初始容量的设定
        ArrayList<String> str = new ArrayList<String>();
        System.out.println("初始化容量"+getArrayListCapacity(str));
    }
    // 通过反射获取elementData值
    public static int getArrayListCapacity(ArrayList<?> arrayList) {
        Class<ArrayList> arrayListClass = ArrayList.class;
        try {
            Field field = arrayListClass.getDeclaredField("elementData");
            field.setAccessible(true);
            Object[] objects = (Object[])field.get(arrayList);
            return objects.length;
        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }
    }

打印结果:初始化容量 0

步骤2:添加元素:容量动态扩容

        str.add("a");
        System.out.println("首次添加元素容量:"+getArrayListCapacity(str)
        				+",元素个数:"+str.size());

首次添加元素容量:10,元素个数:1
底层实现原理

public boolean add(E e) {
	//1. 首次添加元素,原size为0,即size+1 = 1;
	ensureCapacityInternal(size + 1); 
	// 2. 元素存入数组索引位0,并更新size变为1
    elementData[size++] = e;   
    // 3. 始终返回true         
    return true;                       
}

ensureCapacityInternal(int minCapacity): :确保内部容量,上面通过size+1,即每次添加元素 就用原元素数量+1 作为 最小容量需求作为参数 传入该方法

// ensureCapacityInternal 翻译:确保内部容量
private void ensureCapacityInternal(int minCapacity) {
	// 通过和ArrayList初始默认数组对象比较,判断是否第一次添加元素
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { 
    	// 扩容至默认容量DEFAULT_CAPACITY = 10
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); 
    }
    // 然后开始 显示处理容量大小
    ensureExplicitCapacity(minCapacity);
}

ensureExplicitCapacity(int minCapacity)

private void ensureExplicitCapacity(int minCapacity) {
//并发安全:modCount用于检测并发修改,迭代中修改集合会抛出ConcurrentModificationException
    modCount++; 
    //如果最小容量需求 大于 现有数组容量,则进行自动扩容,否则不用扩容量
    if (minCapacity - elementData.length > 0)
        grow(minCapacity); // 触发扩容
}

到这里minCapacity =10 ,elementData.length =0 大于0满足 开始执行自动扩容grow 方法

// 自动扩容方法
private void grow(int minCapacity) {
	//原有数组容量
    int oldCapacity = elementData.length;
    // 1.5倍扩容容量
    int newCapacity = oldCapacity + (oldCapacity >> 1); 
    // 确保满足最小需求,若1.5倍仍不足,直接使用所需最小容量minCapacity
    if (newCapacity < minCapacity) newCapacity = minCapacity; 
    
    // 数组上限处理:确保新容量不超过MAX_ARRAY_SIZE(Integer.MAX_VALUE - 8),
    // 否则调整至Integer.MAX_VALUE。
    if (newCapacity > MAX_ARRAY_SIZE) newCapacity = hugeCapacity(minCapacity);
    
    // 将旧数组数据复制到新数组中,完成扩容
    elementData = Arrays.copyOf(elementData, newCapacity); 
}

Ⅰ.首先添加元素 容量扩容至 默认长度10,触发grow方法 复制到新数组
Ⅱ.添加第11个元素,原容量10不足,再次触发触发grow方法,扩容至15(10 + 5),元素存入索引10,size变为11。

总结
1.数组本身是静态的,无法自动扩容的,初始容量多少就是多少
2.日常需要中无法确认一个数组我们需要多少容量,或者容量的大小是经常变动的,才有了所谓的动态数组,这种动态扩容机制是一种设计理念,其本质是根据最新需求容量比较原有数组容量,返回一个拷贝原数组元素的新数组,Arrays.copyOf返回的是new Object。这种动态扩容机制在StringBuffer等,周期线程池的无阻塞延迟队列等都有使用

常见方法

数组的使用在java中比较多,也封装了很多关于数组方法的类,如Arrays,ArrayList,ArrayDeque,ArrayUtils等,像ArrayList 数组和List集合结合的类,ArrayDeque数组和队列结合的类,这部分在集合中介绍,下面介绍Arrays和ArrayUtils

Arrays

包位于: java.util.Arrays,这是一个JDK自带的工具类,包含了操纵数组的各种方法
核心功能

  • 排序:支持基本类型和对象数组的排序。
  • 搜索:在已排序的数组中快速查找元素。
  • 填充:将数组的所有或部分元素填充为指定值。
  • 比较:判断两个数组是否相等。
  • 复制:生成数组的副本。
  • 转换:将数组转换为列表(List)或字符串(String)。
  • 流操作:支持将数组转换为流(Java 8+)。

排序

1.sort() 排序

功能:数组进行升序排序(支持基本类型和对象

①基本数据类型数组排序
适用于所有基本类型数组(byte, short, int, long, float, double, char),按自然顺序升序排序

int[] numbers = {3, 1, 4, 1, 5};
Arrays.sort(numbers); 
System.out.println(Arrays.toString(numbers));// 排序后打印:[1, 1, 3, 4, 5]

char[] chars = {'z', 'a', 'D', '#'};
Arrays.sort(chars); 
// 结果:['#', 'D', 'a', 'z'](按Unicode值排序)

底层实现

    public static void sort(int[] a) {
        DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
    }

算法实现:基于双轴快速排序(Dual-Pivot Quicksort),适用于基本类型数组(如 int[]、long[])

②对象数组排序(自然顺序)
对象必须实现Comparable接口,按compareTo方法定义的顺序排序
示例

String[] names = {"Alice", "Bob", "Charlie", "David"};
Arrays.sort(names); 
// 结果:["Alice", "Bob", "Charlie", "David"](字典序)

class Person implements Comparable<Person> {
    String name;
    public int compareTo(Person other) {
        return this.name.compareTo(other.name);
    }
}
Person[] people = ...; 
Arrays.sort(people); // 按name字段排序

方法源码

    public static void sort(Object[] a) {
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a);
        else
            ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
    }

TimSort(优化后的归并排序) ,时间复杂度:O(n log n),稳定排序(相等元素顺序不变)

③对象数组排序(自定义顺序)
通过Comparator自定义排序规则,支持灵活排序逻辑
方法签名

static <T> void sort(T[] a, Comparator<? super T> c)

示例

Integer[] numbers = {5, 3, 9, 1, 6};
// 降序排序
Arrays.sort(numbers, (a, b) -> b - a); 
// 结果:[9, 6, 5, 3, 1]

// 按字符串长度排序
String[] words = {"apple", "banana", "kiwi"};
Arrays.sort(words, Comparator.comparingInt(String::length)); 
// 结果:["kiwi", "apple", "banana"]

④部分范围排序
对数组的指定区间进行排序,适用于仅需处理子数组的场景。
方法签名

static void sort(Xxx[] a, int fromIndex, int toIndex) // 基本类型
static <T> void sort(T[] a, int fromIndex, int toIndex, Comparator<? super T> c) // 对象类型

参数说明
fromIndex:起始索引(包含)
toIndex:结束索引(不包含)
异常:若索引越界,抛出IllegalArgumentException或ArrayIndexOutOfBoundsException

2.parallelSort() 排序

支持基本数据 和 对象,和sort方法区别在于 并行排序(大数据量优化),数据量较大(通常超过 10万元素),适用多核CPU环境(核心数 ≥ 4)

static void parallelSort(Xxx[] a) // 基本类型
static <T> void parallelSort(T[] a, Comparator<? super T> cmp) // 对象类型

特点:
①数据规模阈值:Java内部对parallelSort设置了阈值MIN_ARRAY_SORT_GRAN = 8192),小于该值会自动退化为 sort

        if (n <= MIN_ARRAY_SORT_GRAN ||
            (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
            DualPivotQuicksort.sort(a, 0, n - 1);//小于阈值会自动退化为 sort

② 对象排序:对象数组需实现 Comparable 接口或传入 Comparator

总结:
在这里插入图片描述

查找:binarySearch()

binarySearch():二分查找
功能:在已排序的数组中查找元素,返回索引(未找到返回负数)

int[] sorted = {1, 2, 3, 4, 5};
int index1 = Arrays.binarySearch(sorted, 3); // 返回 2
int index2 = Arrays.binarySearch(sorted, 30); // 返回 -6

填充:fill()

fill():将数组的所有或部分元素填充为指定值。

int[] arr = new int[5];
Arrays.fill(arr, 0);        // 填充为 [0, 0, 0, 0, 0]
Arrays.fill(arr, 1, 3, 9);  // 填充索引1到2为9 → [0, 9, 9, 0, 0]

比较:equals() 和 deepEquals()

功能:判断两个数组内容是否相等。
equals():比较一维数组。
deepEquals():深度比较多维数组。

int[] a = {1, 2};
int[] b = {1, 2};
boolean isEqual = Arrays.equals(a, b); // true

int[][] matrix1 = {{1, 2}, {3, 4}};
int[][] matrix2 = {{1, 2}, {3, 4}};
boolean isDeepEqual = Arrays.deepEquals(matrix1, matrix2); // true

复制:copyOf() 和 copyOfRange()

功能:生成数组的副本或部分副本。

int[] original = {1, 2, 3, 4, 5};
int[] copy1 = Arrays.copyOf(original, 3);        // 复制前3个→索引 0 1 2 → [1, 2, 3]
int[] copy2 = Arrays.copyOfRange(original, 1, 4); // 复制索引1到3 → [2, 3, 4]

转换为列表:asList()

功能:将数组转换为固定长度的 List(不可增删元素

String[] names = {"Alice", "Bob", "Charlie"};
List<String> list = Arrays.asList(names); // 支持遍历和修改元素,但不可增删

names[0] = "du"; // list打印 就变成 [du, Bob, Charlie]
list.add("du");// 这里会抛 UnsupportedOperationException

asList() 的陷阱:
1.返回的 List 是基于原始数组的视图,修改数组会影响 List
2.不能对返回的 List 进行增删操作(会抛 UnsupportedOperationException)

转换为字符串:toString() 和 deepToString()

功能:将数组内容转换为可读的字符串形式。两者区别在于作用对象是一维数组和多维数组

int[] arr = {1, 2, 3};
System.out.println(Arrays.toString(arr)); // 输出 [1, 2, 3]

int[][] matrix = {{1, 2}, {3, 4}};
System.out.println(Arrays.deepToString(matrix)); // 输出 [[1, 2], [3, 4]]

多维数组操作方法:使用 deepToString()、deepEquals() 和 deepHashCode() 处理多维数组。这种方法名字带有 deep都是对多维数组的

流操作:stream()

功能:将数组转换为流(Stream),支持函数式编程。

int[] numbers = {1, 2, 3, 4, 5};
int sum = Arrays.stream(numbers).sum(); // 求和 → 15

Arrays总结

Arrays 类是 Java 中通过静态方法封装了数组的常见操作,避免了开发者重复造轮子。它的核心优势包括:
1.代码简洁性:一行代码完成复杂操作(如排序、填充)。
2.性能优化:底层使用高效算法(如快速排序、二分查找)。
3.安全性:避免直接操作数组时的越界错误。
使用建议:在需要处理数组的简单操作时,优先使用 Arrays 类;对于复杂动态数据需求,可结合 ArrayList 或 Stream API

ArrayUtils

位于:commons-lang包 org.apache.commons.lang.ArrayUtils,说明这个是 apache分布的一个辅助包,其功能看名字也是Array工具类,Arrays工具类提供对数组的基本操作方法,ArrayUtils 通过封装底层数组操作,类似于StringUtils,需要进行依赖引入,依赖引入:Apache Commons Lang 3 需添加 Maven 依赖

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.14.0</version>
</dependency>

常见方法介绍

ArrayUtils中的方法:
1.add():将给定的数据添加到指定的数组中,返回一个新的数组。
2.addAll():合并两个数组。
3.contains():检查该数据在该数组中是否存在,返回一个boolean值。
4.getLength():返回该数组长度。
5.indexOf():从数组的第一位开始查询该数组中是否有指定的数值,存在返回index的数值,否则返回-16.lastIndexOf():从数组的最后一位开始往前查询该数组中是否有指定的数值,存在返回index的数值,否则返回-17.Insert():向指定的位置往该数组添加指定的元素,返回一个新的数组。
8.isEmpty():判断该数组是否为空,返回一个boolean值。
9.isNotEmpty():判断该数组是否为空,而不是null10.isSameLength():判断两个数组的长度是否一样,当数组为空视长度为0。返回一个boolean值。
11.isSameType():判断两个数组的类型是否一样,返回一个boolean值。
12.isSorted():判断该数组是否按照自然排列顺序排序,返回一个boolean值。
13.nullToEmpty():
14.remove():删除该数组指定位置上的元素,返回一个新的数组。
15.removeAll():删除指定位置上的元素,返回一个新的数组。
16.removeAllOccurences():从该数组中删除指定的元素,返回一个新的数组。
17.removeElement():从该数组中删除第一次出现的指定元素,返回一个新的数组。
18.removeElements():从该数组中删除指定数量的元素,返回一个新的数组。
19.reverse():数组反转。也可以指定开始和结束的反转位置。
20.subarray():截取数组(包头不包尾),返回一个新的数组。
21.swap():指定该数组的两个位置的元素交换或者指定两个位置后加len的长度元素进行交换。
22.toMap():将数组转换成Map,返回一个map的Object的集合。
23.toObject():将原始数据类型的数组转换成对象类型数组。
24.toPrimitive():将对象类型数组转换成原始数据类型数组。
25.toString():将数组输出为Stirng,返回一个字符串。
26.toStringArray():Object数组转换为String数组类型。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2330871.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

我的NISP二级之路-02

目录 一.数据库 二.TCP/IP协议 分层结构 三.STRIDE模型 四.检查评估与自评估 检查评估 自评估 五.信息安全应急响应过程 六.系统工程 七.SSE-CMM 八.CC标准 九.九项重点工作 记背: 一.数据库 关于数据库恢复技术&#xff0c;下列说法不正确的是&#xff1a…

常见的微信个人号二次开发功能

一、常见开发功能 1. 好友管理 好友列表维护 添加/删除好友 修改好友信息&#xff08;备注、标签等&#xff09; 分组管理 创建/编辑/删除标签 好友分类与筛选 2. 消息管理 信息发送 支持多类型内容&#xff1a;文本、图片、视频、文件、小程序、名片、URL链接等 附加功…

unity的dots中instantiate克隆对象后,对象会在原位置闪现的原因和解决

原因 在Entity中有两个位置信息&#xff0c;一个是local transform。一个是local to world 其中local transform负责具体位置&#xff0c;local to world 负责渲染位置&#xff0c;即图像的渲染的位置是根据local to world的。 local to world 的更新是引擎自己控制的&#x…

R语言——绘制生命曲线图(细胞因子IL5)

绘制生命曲线图&#xff08;根据细胞因子&#xff09; 说明流程代码加载包读取Excel文件清理数据重命名列名处理IL-5中的"<"符号 - 替换为检测下限的一半首先找出所有包含"<"的值检查缺失移除缺失值根据IL-5中位数将患者分为高低两组 创建生存对象拟…

神马系统8.5搭建过程,附源码数据库

项目介绍 神马系统是多年来流行的一款电视端应用&#xff0c;历经多年的发展&#xff0c;在稳定性和易用性方面都比较友好。 十多年前当家里的第一台智能电视买回家&#xff0c;就泡在某论坛&#xff0c;找了很多APP安装在电视上&#xff0c;其中这个神马系统就是用得很久的一…

大模型论文:Improving Language Understanding by Generative Pre-Training

大模型论文&#xff1a;Improving Language Understanding by Generative Pre-Training OpenAI2018 文章地址&#xff1a;https://www.mikecaptain.com/resources/pdf/GPT-1.pdf 摘要 自然语言理解包括各种各样的任务&#xff0c;如文本蕴涵、问题回答、语义相似性评估和文…

[ctfshow web入门] web18

前置知识 js(javascript)语言用于前台控制&#xff0c;不需要知道他的语法是什么&#xff0c;以高级语言的阅读方式也能看懂个大概。 在JavaScript中&#xff0c;confirm()是一个用于显示确认对话框的内置函数&#xff0c;不用知道怎么使用。 信息收集 提示&#xff1a;不要…

`uia.WindowControl` 是什么:获取窗口文字是基于系统的 UI 自动化接口,而非 OCR 方式

uia.WindowControl 是什么:获取窗口文字是基于系统的 UI 自动化接口,而非 OCR 方式 uia.WindowControl 通常是基于 Windows 系统的 UI 自动化框架(如 pywinauto 中的 uia 模块)里用于表示窗口控件的类。在 Windows 操作系统中,每个应用程序的窗口都可以看作是一个控件,ui…

vue3 处理文字 根据文字单独添加class

下面写的是根据后端返回的html 提取我需要的标签和字 将他们单独添加样式 后端返回的数据 大概类似于<h1>2024年“双11”购物节网络零售监测报告</h1><p>表1 “双11” 期间网络零售热销品类TOP10</p> function checkfun(newList){if (newList) {let …

Jupyter Notebook不能自动打开默认浏览器怎么办?

在安装anaconda的过程中,部分用户可能会遇到,打开Jupyter Notebook的时候,不会弹出默认浏览器。本章教程给出解决办法。 一、生成一个jupyter默认配置文件 打开cmd,运行以下命令,会生成一个jupyter_notebook配置文件。 jupyter notebook --generate-config二、编辑jupyter_…

Spring Boot 工程创建详解

2025/4/2 向全栈工程师迈进&#xff01; 一、SpingBoot工程文件的创建 点击Project Structure 然后按着如下点击 最后选择Spring Boot &#xff0c;同时记得选择是Maven和jar&#xff0c;而不是war。因为Boot工程内置了Tomcat&#xff0c;所以不需要war。 紧接着选择Spring We…

Spring Boot + MyBatis + Maven论坛内容管理系统源码

项目描述 xxxForum是一个基于Spring Boot MyBatis Maven开发的一个论坛内容管理系统&#xff0c;主要实现了的功能有&#xff1a; 前台页面展示数据、广告展示内容模块&#xff1a;发帖、评论、帖子分类、分页、回帖统计、访问统计、表单验证用户模块&#xff1a;权限、资料…

国网B接口协议资源上报流程详解以及上报失败原因(电网B接口)

文章目录 一、B接口协议资源上报接口介绍B.2.1 接口描述B.2.2 接口流程B.2.3 接口参数B.2.3.1 SIP头字段B.2.3.2 SIP响应码B.2.3.3 XML Schema参数定义 B.2.4 消息示例B.2.4.1 上报前端系统的资源B.2.4.2 响应消息 二、B接口资源上报失败常见问题&#xff08;一&#xff09;证书…

布谷一对一直播源码android版环境配置流程及功能明细

一&#xff1a;举例布谷交友&#xff08;一对一直播源码&#xff09;搭建部署的基本环境说明 1. 首先安装Center OS 7.9系统&#xff0c;硬盘最低 40G 2. 安装宝塔环境 https://bt.cn&#xff08;强烈推荐使用&#xff09; 3. 安装环境 ● PHP 7.3&#xff08;安装redis扩展…

【Netty4核心原理④】【简单实现 Tomcat 和 RPC框架功能】

文章目录 一、前言二、 基于 Netty 实现 Tomcat1. 基于传统 IO 重构 Tomcat1.1 创建 MyRequest 和 MyReponse 对象1.2 构建一个基础的 Servlet1.3 创建用户业务代码1.4 完成web.properties 配置1.5 创建 Tomcat 启动类 2. 基于 Netty 重构 Tomcat2.1 创建 NettyRequest和 Netty…

【AI学习】初步了解TRL

TRL&#xff08;Transformer Reinforcement Learning&#xff09; 是由 Hugging Face 开发的一套基于强化学习&#xff08;Reinforcement Learning, RL&#xff09;的训练工具&#xff0c;专门用于优化和微调大规模语言模型&#xff08;如 GPT、LLaMA 等&#xff09;。它结合了…

阿里云oss视频苹果端无法播放问题记录

记录一下苹果端视频不可以播放的原因. 看了一下其他视频可以正常播放,但是今天客户发来的视频无法正常播放.咨询过阿里云售后给出的原因是编码格式过高. 需要调整编码格式为:baseline, 下面记录如何使用ffmpeg修改视频的编码格式. 下载文件(可从官方下载) 配置环境变量(系统变…

Ubuntu离线安装mysql

在 Ubuntu 24.04 上离线安装 MySQL 的步骤如下(支持 MySQL 8.0 或 8.4): 一.安装方法 此次安装是按照方法一安装,其它方法供参考: 安装成功截图: 安全配置截图: sudo mysql_secure_installation 登录测试: 方法一:使用 apt-rdepends 下载依赖包(推荐) 1. 在联网…

IntelliJ IDEA下开发FPGA——FPGA开发体验提升__上

前言 由于Quartus写代码比较费劲&#xff0c;虽然新版已经有了代码补全&#xff0c;但体验上还有所欠缺。于是使用VS Code开发&#xff0c;效果如下所示&#xff0c;代码样式和基本的代码补全已经可以满足开发&#xff0c;其余工作则交由Quartus完成 但VS Code的自带的git功能&…

SpringBoot底层-数据源自动配置类

SpringBoot默认使用Hikari连接池&#xff0c;当我们想要切换成Druid连接池&#xff0c;底层原理是怎样呢 SpringBoot默认连接池——Hikari 在spring-boot-autoconfiguration包内有一个DataSourceConfiguraion配置类 abstract class DataSourceConfiguration {Configuration(p…