List集合的进一步学习:性能优化

news/2024/11/29 23:06:55/

================================

||        持续分享系列教程,关注一下不迷路     ||

||                B站视频教程:墨轩大楼               ||

||                知识星球:墨轩编程自习室           ||

================================

        在Java集合框架中,选择合适的集合类型和使用正确的操作方法可以显著提高程序的性能。以下是一些常见的性能优化技巧,并附有详细的代码示例。

1. 选择合适的集合类型

根据具体的需求选择合适的集合类型是性能优化的第一步。例如:

  • 随机访问:如果需要频繁进行随机访问操作,应选择ArrayList
  • 频繁插入/删除:如果需要频繁进行插入和删除操作,应选择LinkedList
  • 线程安全:如果需要在多线程环境下使用,可以考虑Vector或使用Collections.synchronizedList包装ArrayList
2. 批量操作

批量操作通常比单个操作更高效。例如,使用addAll方法一次添加多个元素比多次调用add方法更高效。

示例代码
import java.util.ArrayList;
import java.util.List;public class BatchOperationExample {public static void main(String[] args) {List<String> list = new ArrayList<>();// 单个添加操作long startTime = System.nanoTime();for (int i = 0; i < 1000000; i++) {list.add("Element" + i);}long endTime = System.nanoTime();System.out.println("Single add operations: " + (endTime - startTime) + " ns");// 清空列表list.clear();// 批量添加操作List<String> elements = new ArrayList<>();for (int i = 0; i < 1000000; i++) {elements.add("Element" + i);}startTime = System.nanoTime();list.addAll(elements);endTime = System.nanoTime();System.out.println("Batch add operations: " + (endTime - startTime) + " ns");}
}
3. 避免不必要的扩容

ArrayListVector在内部使用数组来存储元素。当数组容量不足时,会创建一个新的更大的数组,并将旧数组中的元素复制到新数组中。这个过程可能会导致性能下降。可以通过预分配足够的初始容量来避免这种情况。

示例代码
import java.util.ArrayList;
import java.util.List;public class InitialCapacityExample {public static void main(String[] args) {// 默认初始容量List<String> list1 = new ArrayList<>();long startTime = System.nanoTime();for (int i = 0; i < 1000000; i++) {list1.add("Element" + i);}long endTime = System.nanoTime();System.out.println("Default initial capacity: " + (endTime - startTime) + " ns");// 预分配初始容量List<String> list2 = new ArrayList<>(1000000);startTime = System.nanoTime();for (int i = 0; i < 1000000; i++) {list2.add("Element" + i);}endTime = System.nanoTime();System.out.println("Pre-allocated initial capacity: " + (endTime - startTime) + " ns");}
}
4. 使用迭代器进行批量删除

在遍历集合并删除元素时,使用迭代器比直接调用remove方法更高效。直接调用remove方法会导致集合重新计算索引,而使用迭代器则不会。

示例代码
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;public class IteratorRemoveExample {public static void main(String[] args) {List<Integer> list = new ArrayList<>();for (int i = 0; i < 1000000; i++) {list.add(i);}// 使用迭代器删除long startTime = System.nanoTime();Iterator<Integer> iterator = list.iterator();while (iterator.hasNext()) {if (iterator.next() % 2 == 0) {iterator.remove();}}long endTime = System.nanoTime();System.out.println("Using iterator remove: " + (endTime - startTime) + " ns");// 重置列表list.clear();for (int i = 0; i < 1000000; i++) {list.add(i);}// 直接调用remove方法startTime = System.nanoTime();for (int i = 0; i < list.size(); i++) {if (list.get(i) % 2 == 0) {list.remove(i--); // 注意索引调整}}endTime = System.nanoTime();System.out.println("Direct remove: " + (endTime - startTime) + " ns");}
}
5. 减少同步开销

在多线程环境下,尽量减少同步开销。例如,使用CopyOnWriteArrayList代替VectorCollections.synchronizedList包装的ArrayList

示例代码
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;public class SynchronizationExample {private static final int NUM_THREADS = 10;private static final int NUM_OPERATIONS = 10000;public static void main(String[] args) throws InterruptedException {testSynchronization(new ArrayList<>(), "ArrayList with Collections.synchronizedList");testSynchronization(new CopyOnWriteArrayList<>(), "CopyOnWriteArrayList");}private static void testSynchronization(List<Integer> list, String name) throws InterruptedException {if (list instanceof ArrayList) {list = Collections.synchronizedList(list);}ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);long startTime = System.nanoTime();for (int i = 0; i < NUM_THREADS; i++) {executor.submit(() -> {for (int j = 0; j < NUM_OPERATIONS; j++) {list.add(j);}});}executor.shutdown();executor.awaitTermination(1, TimeUnit.MINUTES);long endTime = System.nanoTime();System.out.println(name + ": " + (endTime - startTime) + " ns");}
}
6. 使用缓存

对于频繁访问的数据,可以考虑使用缓存来提高性能。例如,使用ConcurrentHashMap来存储和检索数据。

示例代码
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;public class CacheExample {private static final ConcurrentMap<Integer, String> cache = new ConcurrentHashMap<>();public static void main(String[] args) {// 初始化缓存for (int i = 0; i < 1000000; i++) {cache.put(i, "Value" + i);}// 从缓存中获取数据long startTime = System.nanoTime();for (int i = 0; i < 1000000; i++) {String value = cache.get(i);}long endTime = System.nanoTime();System.out.println("Cache lookup: " + (endTime - startTime) + " ns");}
}

总结

通过选择合适的集合类型、批量操作、预分配初始容量、使用迭代器进行批量删除、减少同步开销以及使用缓存等方法,可以显著提高Java集合框架的性能。希望这些示例代码能够帮助您更好地理解和应用这些性能优化技巧。如果您有任何问题或需要进一步的帮助,请随时提问。


http://www.ppmy.cn/news/1551020.html

相关文章

Flink四大基石之Window

为什么要用WIndow 在流处理应用中&#xff0c;数据是连续不断的&#xff0c;有时我们需要做一些聚合类的处理&#xff0c;例如&#xff1a;在过去的1分钟内有多少用户点击了我们的网页。 在这种情况下&#xff0c;我们必须定义一个窗口(window)&#xff0c;用来收集最近1分钟内…

论文笔记 SliceGPT: Compress Large Language Models By Deleting Rows And Columns

欲买桂花同载酒&#xff0c;终不似&#xff0c;少年游。 数学知识 秩&#xff1a; 矩阵中最大线性无关的行/列向量数。行秩与列秩相等。 线性无关&#xff1a;对于N个向量而言&#xff0c;如果任取一个向量 v \textbf{v} v&#xff0c;不能被剩下的N-1个向量通过线性组合的方式…

SplatFormer: Point Transformer for Robust3D Gaussian Splatting 论文解读

目录 一、概述 二、相关工作 1、NVI新视角插值 2、稀疏视角重建 3、OOD-NVS 4、无约束重建下的正则化技术 5、基于学习的2D-to-3D模型 6、3D点云处理技术 三、SplatFormer 1、Point Transformer V3 2、特征解码器 3、损失函数 四、数据集 五、实验 一、概述 该论…

shell编程(8)

目录 一、until循环 示例 until 和 while 的区别 二、case语句 基本语法 示例 1. 简单的 case 语句 2. 使用通配符 3. 处理多个匹配 case 和 if 的比较 case 语句&#xff1a; if 语句&#xff1a; 三、基本函数 基本函数定义和调用 1. 定义一个简单的函数 2. …

git常用命令和问题

git不能推送 merge时的解决方法&#xff1a; git rebase git stash # 每次 push 前 git pull --rebase git push origin HEAD:refs/for/master # gerrit review git pull git stash pop 常用命令&#xff1a; 合并dev分支 a 切换到master分支 git checkout master b…

基于RAG的text2sql解决方案vanna-ai 私有化部署使用实战

1 安装python 虚拟环境 安装 Miniconda3 Step 1: 下载 $ wgethttps://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh Step2: 运行脚本 $ sh Miniconda3-latest-Linux-x86_64.sh Step3: 设置环境变量 vi /etc/profile export PATH“/data/apps/minic…

Redis的基础知识·

Redis是一个基于内存的key-value的结构数据库 基于内存存储 读写性能高适合存储热点数据&#xff08;热点商品 咨询 新闻&#xff09; 开启Redis 首先输入命令 redis-server.exe redis.windows.conf 然后重新打开命令行窗口 输入命令 redis-cli.exe 输入密码 …

数据分析:彩票中奖号码分析与预测

预测双色球彩票的中奖号码是一个典型的随机事件&#xff0c;因为每个号码的出现概率是独立的&#xff0c;且历史数据并不能直接用于预测未来的开奖结果。然而&#xff0c;我们可以通过统计分析来了解号码的分布规律&#xff0c;从而提供一些可能的参考。 样例数据【点击下载】…