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

ops/2024/11/29 10:02:04/

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

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

||                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/ops/137621.html

相关文章

注意http-proxy-middleware要解决跨域问题,想修改origin请求头不要设置changeOrigin=true

在使用http-proxy-middleware的时候&#xff0c;有一个配置是“changeOrigin”&#xff0c;通过名字来看这个字段是用来控制是否修改origin的&#xff0c;但是实际使用下来&#xff0c;你会发现&#xff0c;当设置为true的时候&#xff0c;header中的origin的值并不会修改&…

4、常量和进制转换

1、常量 1.1、常量 常量是在程序运行中值不能内改变&#xff08;常数&#xff09;。 整型:12 55 实型:21.5 字符型常量: ‘A’ 1.2、常量不同进制表示 常量数据在计算机中除了用 十进制 表示&#xff0c;还可以用 二进制、八进制、十六进制表示。 十进制数据&…

快手守城之战

科技新知 原创作者丨樱木 编辑丨蕨影 双11过后&#xff0c;大厂来到了交卷时刻。三季度虽然是传统的淡季&#xff0c;但在电商重新洗牌、短视频流量见顶的关键之年&#xff0c;此刻的平淡则显得异常扎眼。 从业务类型来看&#xff0c;略显保守的快手似乎成了资本狙击的对象&a…

5G基础学习笔记

功能软件化 刚性网络&#xff1a;固定连接、固定功能、固化信令交互 柔性网络&#xff1a;网元拆解成服务模块&#xff0c;基于API接口调用 服务化架构&#xff08;SBA&#xff09; Service based Architecture &#xff08;SBA&#xff09;: 借鉴了业界成熟的SOA、微服务架…

蓝桥杯备赛笔记(一)

这里的笔记是关于蓝桥杯关键知识点的记录&#xff0c;有别于基础语法&#xff0c;很多内容只要求会用就行&#xff0c;无需深入掌握。 文章目录 前言一、编程基础1.1 C基础格式和版本选择1.2 输入输出cin和cout&#xff1a; 1.3 string以下是字符串的一些简介&#xff1a;字符串…

HNU信息安全数学基础实验二

一、实验内容 编程实现&#xff1a;模重复平方法&#xff08;非伪码&#xff09;。 二、实验目标 1. 理解模重复平方方法的算法原理及其应用场景。 2. 编写代码实现该算法&#xff0c;并能够正确处理大数幂次运算中的模运算。 3. 通过实验验证算法的正确性和效率&#xff…

stm32 振动传感器实现检测震动 灯亮2s 设置标志位

标志位的作用就是传递事件的发生信息。中断处理程序只负责响应外部事件&#xff0c;然后通过设置标志位来让主程序来处理实际的逻辑。 在中断服务例程&#xff08;ISR&#xff09;中&#xff0c;应该避免做任何复杂的操作或延时&#xff0c;因为中断服务程序执行时会中断主程序…

《手写Spring渐进式源码实践》实践笔记(第十九章 实现事务管理@Transactional注解)

第十九章 事务管理 背景 事务 事务&#xff08;Transaction&#xff09;是一个不可分割的工作单位&#xff0c;它由一组有限的数据库操作序列组成。在计算机术语中&#xff0c;事务是指访问并可能更新数据库中各种数据项的一个程序执行单元。事务是为了保证数据库的一致性而…