Java数组深度剖析:掌握数据结构的基石

news2024/11/26 23:55:59

引言

        在编程世界中,数仅仅是一种数据类型,它是理解内存分配、多维数据处理以及性能优组像是构建复杂数据结构的基本积木。它们简洁、高效,是管理元素集的首选方式。在Java中,数组不化的关键。

        这篇文章致力于深入探讨Java数组的各个方面,从声明和初始化,到高级操作和实际应用。不论你是初次步入Java编程领域的新手,还是求知欲旺盛、渴望提升技术深度的老手,这篇文章都会是你理解数组如何在Java中玩转的宝典。        

Java数组的ABC

定义与声明

        Java数组是存储固定大小的相同类型元素的线性数据结构。说它固定大小意味着一旦你声明了数组的长度,在其生命周期中,这个长度是不可改变的。这是初学者在设计程序时必须牢记的重点。

        声明一个数组的方式多种多样,但最常见的无非两种模式:要么声明再实例化,要么同时进行。举个例子,这是如何声明一个整型数组:

int[] myArray;

        或者,你也可以选择另一种风格:

int myArray[];

        两种风格都可以使用,但前者在Java社区中更受青睐。值得注意的是,数组名后的方括号指出了"myArray"是一个数组变量,而不是一个基本的整型变量。

数组初始化

        当然,仅仅声明数组并不能使其发挥作用,我们还需要进行初始化。可以将初始化分为两类:静态和动态。静态初始化像是一行代码就囊括了创建数组和赋值的全过程,简洁直观:

int[] staticArray = {1, 2, 3, 4, 5};

        上面的例子同时声明并初始化了一个整型数组。编译器能够通过你提供的值推断出数组的长度。反观动态初始化,在声明数组时并没有给出具体的值。这就需要我们使用关键字new来创建数组,并且指定数组应有的容量:

int[] dynamicArray = new int[5];

        随后,我们可以使用循环来填充数组,抑或根据算法生成数组元素的值。例如,通过一个简单的for循环来为数组赋初始值:

for(int i = 0; i < dynamicArray.length; i++) {
    dynamicArray[i] = i * 10;
}

        在上述代码中,dynamicArray每个位置上的数值是其索引的10倍。dynamicArray.length属性确保了我们不会越界访问数组,这一点在处理数组时至关重要。

数组元素访问

        数组初始化完毕后,接下来的自然步骤就是元素访问和修改了。Java中通过索引,即数组中每个元素的位置编号来实现访问。索引是从零开始的,这也就是说,第一个元素的索引是0,最后一个元素的索引是数组长度减1。

        阅读到这里,你可能会好奇,如果我试图访问一个不存在的索引会发生什么?答案是Java将会抛出ArrayIndexOutOfBoundsException异常。要避免这种情况,我们总是需要确保索引在数组边界之内。

        为了提供一个快速的橡胶,让我们取出动态数组的第一个元素,并将其更新:

int firstElement = dynamicArray[0]; // 获取第一个元素
dynamicArray[0] = 10;               // 将第一个元素的值设置为10

        试图访问dynamicArray[5](在我们的例子中是个不存在的索引)将会导致异常。

数组的操作与算法

        掌握数组基础后,我们进入更精彩的部分 —— 数组的操作与算法。对于程序员而言,了解如何有效操作数组同样重要,因为这关系到程序的性能和可读性。

典型的数组操作

        数组的基础操作包括添加(或插入)、删除、修改和遍历。在实践中,我们通常会采用分步逐个掌握的方式。

  • 插入元素 —— 如果数组未满,你可以在数组末尾插入新元素。但如果想在数组中间某个位置插入元素,就需要将该位置及其后的元素都向后移动一位,这会有一定的性能开销。
  • 删除元素 —— 类似地,删除数组中的元素意味着你需要将被删除元素之后的所有元素都向前移动一位。
  • 数组的遍历 —— 为了访问数组中的每个元素,你可以使用循环结构。Java提供了for循环和增强型for循环,后者对遍历操作更为方便。

        举个例子,假设我们有一个整型数组numbers,并想打印出所有元素:

int[] numbers = {2, 4, 6, 8, 10};
for(int number : numbers) {
    System.out.println(number);
}

排序与搜索

        在数组的世界里,排序和搜索是最常见的算法之一。对数组进行排序通常是为了提高搜索效率或使输出结果更加有序。

  • 排序 —— Java提供了内置的Arrays.sort()方法来对数组进行排序。此外,你还可以实现你自己的排序算法,如快速排序、归并排序等。
  • 搜索 —— 在经过排序的数组中搜索元素显得更加高效。常见的搜索算法包括线性搜索和二分搜索。

        如果我们希望在numbers数组中查找数字6是否存在,可以先对数组排序,再使用二分搜索法:

Arrays.sort(numbers); // 排序数组
int index = Arrays.binarySearch(numbers, 6); // 搜索值6
System.out.println("Index of 6: " + index);

多维数组与复杂数据结构

        多维数组是学习数组不可或缺的一部分,特别是在涉及到高级数学计算和图像处理时。在Java中,可以通过嵌套数组的方式来创建多维数组,最常见的是二维数组。

声明和使用多维数组

        声明一个二维数组可以这样理解:每个数组元素本身也是一个数组。以下是如何声明、初始化和访问一个二维数组:

int[][] matrix = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

// 访问第一行第二列的元素
int element = matrix[0][1];
System.out.println(element); // 输出 2

操作多维数组

        操作多维数组与一维数组相似,但需要额外的注意遍历和索引管理。比如,你可以使用两层嵌套循环来遍历一个二维数组。

复杂数据结构

        掌握了多维数组后,你就迈出了进一步理解更复杂数据结构的第一步。例如,你可以使用二维数组来模拟棋盘游戏、处理图像数据,或者构建更高级的数据结构如矩阵。

Java特有数组操作

        Java作为一种成熟的编程语言,提供了一套强大的工具和类库来简化数组的日常使用。这些工具不仅增加了编码的便利性,还极大地提升了开发效率。

Arrays类

        在java.util包中,Arrays类为数组操作提供了一系列的静态方法。比如,你可以使用它来进行排序、搜索、比较数组、填充数组以及转化数组为集合等操作。

        以下是一些Arrays类中常用方法的示例:

int[] array = {3, 6, 1, 4, 9};

// 排序
Arrays.sort(array);
System.out.println("Sorted array: " + Arrays.toString(array));

// 搜索
int index = Arrays.binarySearch(array, 4);
System.out.println("Index of 4: " + index);

// 比较
int[] arrayCopy = array.clone();
System.out.println("Arrays are equal: " + Arrays.equals(array, arrayCopy));

// 填充
Arrays.fill(array, 10);
System.out.println("Filled array: " + Arrays.toString(array));

Java 8的流操作

        从Java 8开始,Stream API允许你将数组转化为流并进行序列化处理。利用流操作,你可以使用声明性方式来表达复杂的数据处理逻辑,如映射、过滤、汇总等。

        让我们来看看流操作是如何在数组上应用的:

Integer[] numbers = {2, 3, 5, 7, 11};

// 转换为流、过滤、并计算结果
int sumOfPrimes = Arrays.stream(numbers)
                        .filter(n -> n > 2)
                        .reduce(0, Integer::sum);
System.out.println("Sum of primes greater than 2: " + sumOfPrimes);

数组的进阶应用

        掌握了数组的基础操作和Java特有的数组操作后,让我们继续探索数组在现代编程实践中的进阶应用。

数组在数据结构中的应用

        数组是构造复杂数据结构如栈、队列和堆的基础。通过对简单数组的操作,你可以实现这些数据结构,并对其性能进行优化。

        例如,栈可以通过如下方式使用数组实现:

public class Stack {
    private int[] elements;
    private int size;

    public Stack(int capacity) {
        elements = new int[capacity];
    }

    public void push(int element) {
        if (size < elements.length) {
            elements[size++] = element;
        }
    }

    public int pop() {
        if (size > 0) {
            return elements[--size];
        }
        throw new EmptyStackException();
    }
}

数组在算法中的应用

        数组广泛应用于算法设计中,特别是在动态规划和回溯算法中。你可以使用数组来追踪状态变化,或者存储子问题的解决结果以供后用。

        举个动态规划算法的例子:

public int fib(int n) {
    if (n <= 1) {
        return n;
    }
    int[] fibCache = new int[n + 1];
    fibCache[1] = 1;

    for (int i = 2; i <= n; i++) {
        fibCache[i] = fibCache[i - 1] + fibCache[i - 2];
    }
    return fibCache[n];
}

        在上面的示例中,我们用数组来存储斐波那契数列的计算结果,避免了重复计算,从而提升了效率。

实际案例研究

        理论知识在实际应用中得以锻造与提炼。下面,我们将深入探讨数组在实际项目中的几个案例study。

业务逻辑中的数组应用

        在业务逻辑中,数组通常被用来管理和操作一系列相似或相关的数据。例如,在客户关系管理系统(CRM)中,销售人员需要追踪潜在客户的列表。这样的列表可以很自然地映射为数组,每个潜在客户作为一个元素。

        此外,数组在财务计算中也扮演重要角色。考虑到一份资产组合管理表,编制每个季度的投资回报率,这样的数据组织可以清晰地反映在一个二维数组中,其中行代表时间周期,列代表不同的投资项目。

例如:

public class InvestmentPortfolio {

    public static void main(String[] args) {
        // 假设这是过去四个季度(一年)的投资回报率,二维数组的每一行代表一个季度
        // 每一列代表不同的投资项目
        double[][] returns = {
            {0.10, 0.15, -0.02}, // 第一个季度的投资回报率
            {0.05, -0.05, 0.04}, // 第二个季度的投资回报率
            {0.12, 0.06, -0.01}, // 第三个季度的投资回报率
            {-0.03, 0.07, 0.05}  // 第四个季度的投资回报率
        };
        
        // 计算每个季度的综合回报率,并打印
        for(int i = 0; i < returns.length; i++) {
            double totalReturn = 0;
            for(int j = 0; j < returns[i].length; j++) {
                totalReturn += returns[i][j];
            }
            System.out.println("第 " + (i + 1) + " 季度的综合回报率: " + totalReturn);
        }
        
        // 计算每个投资项目的平均回报率
        for(int i = 0; i < returns[0].length; i++) {
            double sum = 0;
            for(int j = 0; j < returns.length; j++) {
                sum += returns[j][i];
            }
            double averageReturn = sum / returns.length; 
            System.out.println("投资项目 " + (i + 1) + " 的平均回报率: " + averageReturn);
        }
    }
}

a5c3cf46542f43969f0e67d341826d25.png​​​​​​​

        在上述代码中,我们使用二维数组returns来表示投资回报率,其中数组的行表示时间周期(例如季度),列表示不同的投资项目。通过二维数组,我们可以轻松计算出每个季度的总回报率或每个投资项目在一年中的平均回报率。

性能分析和优化实例

        性能优化是软件工程的关键组成部分。以排序算法为例,根据数据的大小和特性来合理选择排序算法,可能会显著提高应用程序的响应时间。例如,对小数组使用插入排序可能比快速排序更为高效。

        在处理大型数据集时,考虑到内存使用和速度效率,合理选择对数组的操作(如逐项插入或大块复制)也同样重要。

数组与数据库的交互

        现代应用程序中常见的一个挑战是处理和存储大量数据。在与数据库交互时,程序员需要用数组来缓存检索的数据和准备批量的数据库更新。通过这种方式,可以减少网络延迟和数据库的访问频率,提升整体性能。

 


常见问题解答与最佳实践

        在深入了解Java数组及其用例之后,让我们来看一些常见的问题和最佳实践,以确保你可以高效且安全地使用数组。

如何处理数组大小不变的限制?

        这个问题可以通过使用集合框架(如ArrayList)来解决,它们在需要时可以动态扩展大小。当需要数组的性能,同时又希望动态调整大小时,集合类提供了一个完美的解决方案。

在哪些情况下应该选择数组,而不是其他数据结构?

        数组应该在需要快速访问固定数量元素的情况下使用。由于数组具有连续的内存布局和索引系统,所以在访问元素时可以提供最佳性能。然而,如果你的数据需求是动态变化的,或者需要频繁的插入和删除操作,那么使用其他数据结构如LinkedList可能更为合适。

为提升数组操作的性能和可读性,你有哪些技巧?

        保证性能的关键在于减少不必要的数组操作和避免处理超出数组长度的操作。例如,知道何时使用System.arraycopy()而非手动复制,可以大大提升你的程序效率。这个方法在Java系统级别进行优化,比循环复制要快得多。

        为了提升代码的可读性,你可以使用增强for循环或Java 8的Stream API。这些工具可以帮助你写出更清晰、更简洁的代码,同时也使得代码更易于理解和维护。

结论

        当我们回顾整个关于Java数组的探索旅程时,我们可以看到数组作为一种基本且强大的数据结构,在Java编程世界中占据着不可忽视的地位。从简单的数组声明,到深层次的性能优化,数组一直是高效信息管理和算法实现中不可或缺的一部分。

        我们证实了对于那些需要高速访问和操作大量统一数据类型的应用来说,数组无疑是最合适的选择。由于它们的简洁性和一致的内存布局,数组在执行时间关键型任务时表现出了卓越的性能。同时,通过Arrays类及Java 8的Stream API,我们无需牺牲编程的便捷性和代码的可读性。

        在掌握了数组的基本操作之后,我们进一步探讨了如何将其应用于更复杂的数据结构和算法中,从而在解决实际问题时发挥其作用。无论是在构建数据结构、处理批量数据还是在性能关键型系统中,数组都显示了其不可动摇的地位。

        进一步,通过实际案例研究,我们了解了如何在真实世界中有效地应用数组。同时,通过回答常见问题并分享最佳实践,我们为读者提供了关于如何提高工作效率以及预防常见编程错误的指导。

        总而言之,虽然在某些场合其他数据结构可能更为合适,但数组因其在许多编程场景中的高效性和可靠性而依然是Java编程的基石。随着Java语言和其生态系统的不断发展,数组的概念和应用将会进一步深化和扩展,而掌握好数组的应用既是加强程序员基本功的一种方式,也是推动更高级编程技巧发展的基础。

        正如本文所展现的,数组不仅仅是一个工具或对象,它更是一种思考问题和解决问题的方法。随着技术的不断进步,我们期待着数组在未来能够带来更多强大且高效的编程模式。

章节关键概念说明示例或备注
1. 引入重要性和应用场景数组在编程和数据处理中的基础作用-
2. Java数组的ABC   
2.1 定义与声明语法及类型对数组的基本定义和声明方式int[] array; 或 int array[];
2.2 数组初始化静态与动态如何初始化数组的两种基本方法静态: int[] arr = {1, 2, 3};, 动态: int[] arr = new int[3];
2.3 数组元素访问索引和边界获取和设置数组元素的方法,以及如何安全地处理arr[0] = 10;, 检查 arr.length
3. 数组的操作与算法   
3.1 典型的数组操作插入、删除、修改数组元素的基本操作-
3.2 数组遍历for和forEach多种遍历数组的方法for: for (int i : arr) {}, forEach (Java 8+): Arrays.stream(arr).forEach(...);
3.3 排序与搜索排序方法、搜索技术如何排序和搜索数组内置: Arrays.sort(arr), 搜索: Arrays.binarySearch(arr, key)
4. 多维数组与复杂数据结构   
4.1 多维数组的声明和使用多维数据表示多维数组的用法和例子int[][] matrix = {{1,2}, {3,4}};
4.2 多维数组数据操作数据填充、检索多维数组的复杂操作使用嵌套循环进行数据检索
5. Java特有数组操作   
5.1 Arrays类的深度利用Arrays类API介绍Arrays类中的方法例如:Arrays.copyOfArrays.equals
5.2 Java 8及以后版本的特性Lambda和Stream API使用Java 8的新特性处理数组Stream.of(arr).map(...)...
6. 数组的进阶应用   
6.1 数组在数据结构中的使用队列、栈、堆如何用数组实现基础数据结构代码示例:用数组实现一个简单的栈
6.2 数组在算法中的应用动态规划、回溯使用数组来优化算法动态规划例子:斐波那契数列的计算
7. 实际案例研究   
7.1 业务逻辑数组应用CRM系统数组在商业逻辑中的用例客户的数组列表管理
7.2 性能分析和优化性能调优性能优化实例及技巧如何根据数据特性选择排序算法
7.3 数组与数据库的交互批量数据处理数据库操作优化使用数组缓存和批量更新数据
8. 常见问题解答与最佳实践   
8.1 数组大小问题动态数组介绍如何处理数组大小固定的限制使用ArrayList等集合类
8.2 内存溢出和性能优化性能和内存管理提供内存使用和性能优化技巧数组分配和避免无谓操作
8.3 安全性和可维护性代码质量代码安全性和可维护性的建议代码审查和测试
9. 结论不可替代性、未来趋势数组的作用及其在未来的发展-
10. 附录资源链接、工具和材料提供有用资源和进一步阅读材料的链接-
11. 参考资料学术、官方和推荐读物推荐阅读和研究的相关资料官方Java文档, 推荐书籍等

 

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

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

相关文章

PhotosCollage for Mac:优雅且实用的照片拼贴软件

PhotosCollage for Mac是一款优雅且实用的照片拼贴软件&#xff0c;为Mac用户提供了一个便捷、高效的平台&#xff0c;以创建精美、个性化的照片拼贴作品。 PhotosCollage for Mac v1.4.1激活版下载 该软件界面简洁直观&#xff0c;操作便捷。用户只需将想要拼贴的照片拖入“照…

java案例-服务端与客户端(传输对象)

需求 代码 SysUser 用户类Operation 操作类Client 客户端Server 服务端ServerReaderThread 服务端线程类 SysUser 用户类 需要实现Serializable 方便序列化&#xff0c;传输对象 public class SysUser implements Serializable {private String username;private String passwo…

欧科云链:为什么减半对比特币生态的影响正在逐步“减弱”?

出品&#xff5c;OKG Research 作者&#xff5c;Jason Jiang 欧科云链OKLink数据显示&#xff0c;比特币于区块高度840000&#xff08;北京时间2024年4月20日8:09&#xff09;成功完成第四次减半&#xff0c;比特币挖矿奖励正式由6.25BTC减少至3.125BTC。此次减半之后&#x…

RT-Thread之线程管理(线程的基础概念和使用)

文章目录 前言一、RT-Thread线程的概念二、线程的创建与删除2.1用户线程和系统线程2.2线程控制块2.3线程栈2.4入口函数 三、线程的创建和启动3.1线程创建的种类3.2动态创建线程3.3静态创建线程 总结 前言 本篇文章来给大家讲解RT-Thread中的线程管理&#xff0c;线程管理是属于…

GD32E103C8T6 封装LQFP-48 GigaDevice(兆易创新) 单片机

GD32E103C8T6 是由GigaDevice&#xff08;兆易创新&#xff09;公司生产的一款基于ARM Cortex-M4内核的32位MCU&#xff08;微控制器&#xff09;。以下是GD32E103C8T6的一些主要功能和参数介绍&#xff1a; 主要功能&#xff1a; 高性能ARM Cortex-M4内核: 采用120MHz的ARM …

Matlab实现CNN-BiLSTM模型,对一维时序信号进行分类

1、利用Matlab2021b训练CNN-BiLSTM模型&#xff0c;对采集的一维时序信号进行分类二分类或多分类 2、CNN-BiLSTM时序信号多分类执行结果截图 训练进度&#xff1a; 网络分析&#xff1a; 指标变化趋势&#xff1a; 代码下载方式&#xff08;代码含数据集与模型构建&#xff0…

iview 自定义项求和的方法和错误点

这是iview自定义某几项参数合计的方法&#xff0c;其实是蛮简单的&#xff0c;很多人自定义合计的时候&#xff0c;老是会不知道怎么处理除了需要合计的几项的其他项&#xff0c;其实不需要管&#xff0c;不需要合计的项直接返回空就好了&#xff0c;需要的就在计算的里面做key…

MyBatis 核心配置讲解(下)

大家好&#xff0c;我是王有志&#xff0c;一个分享硬核 Java 技术的互金摸鱼侠。 我们书接上回&#xff0c;继续聊 MyBatis 的核心配置&#xff0c;我们今天分享剩下的 5 项核心配置。 不过正式开始前&#xff0c;我会先纠正上一篇文章 MyBatis 核心配置讲解&#xff08;上&…

【链表——数据结构】

文章目录 1.单链表1.定义2.基本操作2.1.不带头结点2.2后插2.3前插2.4删除2.5按位查找2.6按值查找2.7求单链表长度2.8 建表 2.双链表1.初始化2.插入(后插)3.删除(后删)4.遍历 3.循环链表1.循环单链表2.循环双链表3.代码问题 4.静态链表1.简述基本操作的实现1.初始化3.删除某个结…

【AIGC调研系列】Sora级别的国产视频大模型-Vidu

Vidu能够达到Sora级别的标准。Vidu被多个来源认为是国内首个Sora级别的视频大模型[2][3][4]。它采用了团队原创的Diffusion与Transformer融合的架构U-ViT&#xff0c;能够生成长达16秒、分辨率高达1080P的高清视频内容[1][6]。此外&#xff0c;Vidu的一致性、运动幅度都达到了S…

vue2如何创建一个项目?

目录 1. 安装环境&#xff1a; 2. 安装Vue CLI 3. 创建新项目 4. 选择配置 5. 安装依赖并运行 6. 开始开发 7. 构建项目 8. 预览生产环境构建 首先创建一个vue2项目&#xff0c;你可以通过以下步骤进行&#xff1a; 1. 安装环境&#xff1a; 保证自己的电脑已经安装N…

Jmeter Beanshell 设置全局变量

//获取token import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONArray; import java.util.*; import org.apache.jmeter.util.JMeterUtils; //获取可上机机器 String response prev.getResponseDataAsString(); JSONObject responseObect JSONObjec…

rancher/elemental 构建不可变IOS(一)

一、什么是elemental Elemental 是 Rancher 的一个变种&#xff0c;专注于提供一个更轻量级的 Kubernetes 发行版。它旨在提供简化的部署和管理体验&#xff0c;同时保持 Kubernetes 的灵活性和强大功能。Elemental 通常针对较小的部署场景或资源受限的环境&#xff0c;例如测…

PY32F040单片机产品介绍,LQFP封装,带LCD 驱动器

PY32F040单片机搭载了 Arm Cortex-M0内核&#xff0c;最高主频可达72 MHz&#xff0c;专为高性价比、高可靠性的系统而设计&#xff0c;符合消费市场的基本设计需求。可广泛应用于电机控制、手持设备、PC 外设、以及复杂的数字控制应用等领域。 PY32F040片内集成 UART、I2C、S…

Pycharm配深度学习环境所遇到的部分问题

问题1&#xff1a;Anaconda prompt界面安装CUDA出现的问题: 不管是&#xff1a;conda install pytorch torchvision torchaudio cudatoolkit11.3 -c pytorch 还是:pip ****什么的 问题描述&#xff1a;EnvironmentNotWritableError: The current user does not have write p…

手动在Ubuntu22.04上部署LAMP环境

简介 LAMP环境是常用的Web开发环境之一&#xff0c;其中LAMP分别代表Linux、Apache、MySQL和PHP。本文介绍如何在Ubuntu操作系统的ECS实例内部署LAMP环境。 准备工作 该实例必须满足以下条件&#xff1a; 实例已分配公网IP地址或绑定弹性公网IP&#xff08;EIP&#xff09;。…

【Java】java实现文件上传和下载(上传到指定路径/数据库/minio)

目录 上传到指定路径 一、代码层级结构 二、文件上传接口 三、使用postman进行测试&#xff1b; MultipartFile接收前端传递的文件&#xff1a;127.0.0.1:8082/path/uploadFile part接收前端传递的文件&#xff1a;127.0.0.1:8082/path/uploadFileByRequest 接收前端传递…

【存储芯片】CS创世 SD NAND:可以机贴的存储芯片

什么是CS创世 SD NAND呢&#xff1f;很多的朋友一直想知道这个问题。今天精心准备了SD NAND 的一个介绍。其实很多工程师朋友对CS创世 SD NAND有很多称呼。比如&#xff1a;贴片式T卡、贴片式TF卡、贴片式SD卡、可焊接的T卡&#xff0c;可焊接的SD卡&#xff0c;可贴片的TF卡&a…

TikTok引流中海外云手机的实用功能分享

在当下&#xff0c;TikTok已成为全球范围内最受欢迎的社交媒体平台之一&#xff0c;拥有着庞大的用户群体和潜在的商业机会。为了在TikTok上实现更好的引流效果&#xff0c;利用海外云手机成为了一个明智的选择。接下来&#xff0c;我们将深入探讨海外云手机的功能以及它如何助…

LLM优化:开源星火13B显卡及内存占用优化

1. 背景 本qiang~这两天接了一个任务&#xff0c;部署几个开源的模型&#xff0c;并且将本地经过全量微调的模型与开源模型做一个效果对比。 部署的开源模型包括&#xff1a;星火13B&#xff0c;Baichuan2-13B, ChatGLM6B等 其他两个模型基于transformers架构封装&#xff0…