实战小技巧8:容器的初始化大小指定

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 容器可以说是我们日常开发中,除了基本对象之外,使用最多的类了,那么平时在使用的时候,是否有主意到良好编程习惯的大佬,在创建容器的时候,一般会设置size;那么他们为什么要这么干呢?是出于什么进行考量的呢?今天我们将针对最常见的List/Map/Set三种容器类型的初始化值选择,进行说明

容器可以说是我们日常开发中,除了基本对象之外,使用最多的类了,那么平时在使用的时候,是否有主意到良好编程习惯的大佬,在创建容器的时候,一般会设置size;那么他们为什么要这么干呢?是出于什么进行考量的呢?


今天我们将针对最常见的List/Map/Set三种容器类型的初始化值选择,进行说明


1. List



列表,在我们日常使用过程中,会接触到下面几个


  • ArrayList: 最常见的数组列表
  • LinkedList: 基于链表的列表
  • CopyOnWriteArrayList: 线程安全的数组列表


接下来逐一进行说明


1.1 ArrayList


现在以ArrayList为例,进行源码分析,当我们不指定列表大小,直接创建时

public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
复制代码


上面是内部实现,其中elementData就是列表中存数据的数组,初始化为默认数组

当我们第一次添加一个元素时,发现数组为默认值,会触发一次数组扩容,新的数组大小为10 (详情看源码)


其次就是数组的库容机制,通过源码/网上分享知识点可以知道,这个扩容的实现如下


  • 当新添加的元素,数组放不下时,实现扩容
  • 扩容后的大小 = 扩容前大小 + max(添加元素个数, 1/2 * 扩容前大小)


基于上面的知识点,大致可以得出指定列表长度的好处


  • 节省空间(用多少申请多少,避免浪费)
  • 减少扩容带来的拷贝(扩容一次就会带来一次数组拷贝,如果已知列表很大,结果还使用默认的10,这会产生很多可避免的扩容开销)


1.2 LinkedList


基于链表的列表,不同于上面的数组列表,它没有提供指定大小的构造方法,why?

因为链表本身的数据结构的特点,它就像糖葫芦一样,一个串一个,有数据,才有接上的可能,因此不需要指定大小


1.3 CopyOnWriteArrayList


这个又非常有意思,它同样不能指定大小,但是原因与前面不同,主要在于它保证线程安全的实现方式


  • 每次新增/修改(加锁,保证单线程访问),都是在拷贝的数组操作;完成之后,用新的替换旧的


所以说,每次变更,都会存在数组拷贝,因此就没有必要提前指定数组大小

那么它的初始化每次都使用默认的么?


并不是这样的,当我们已知这个列表中的值时,推荐使用下面这种方式


List<String> values= Arrays.asList("12", "220", "123");
List<String> cList = new CopyOnWriteArrayList<>(values);
复制代码
  • 将初始化值,放在一个普通的列表中,然后利用普通列表来初始化

CopyOnWriteArrayList


2.Map



常见的map容器使用,大多是下面几个

  • HashMap
  • LinkedHashMap: 有序的hashmap
  • TreeMap: 有序的hashmap
  • ConcurrentHashMap: 线程安全的map


2.1 HashMap


HashMap的底层数据结构是 数组 + 链表/红黑树,关于这个就不细说了

我们在初始化时,若不指定size,则数组的默认长度为8(请注意,Map的数组长度是2的倍数)


与ArrayList的扩容时机不一样的是,默认情况下,Map容量没满就会触发一次扩容

默认是数量达到 size * 0.75(0.75为扩容因子,可以在创建时修改),就会触发一次扩容


why?


  • 主要是为了减少hash冲突


同样的为了减少冲突,在初始化时,我们需要指定一个合适大小

比如我们


  • 已知map的数量为2,这个时候Map的大小选择因该是4
  • map数量为6,这个时候Map的大小选择是16


有时候让我们自己来计算这个值,就有些麻烦了,这个时候,可以直接使用Guava的工具类来完成这个目的


Map<String, String> map = Maps.newHashMapWithExpectedSize(6);
复制代码


2.2 LinkedHashMap


初始化方式同上,略


2.3 ConcurrentHashMap


初始化方式同上,略


2.4 TreeMap


不同于上面几个的是treeMap,没有提供指定容器大小的构造方法

原因和前面说到的LinkedList有些类似,TreeMap的底层数据结构为Tree,所以新增数据是挂在树的一个节点下面,无需指定容量大小


3. Set



集合用的最多应该就是HashSet了,底层结构模型复用,所以初始化大小指定与HashMap一致,也不需要多说


4. 小结



今天这篇博文主要介绍的是三种常见的容器,在创建时,如何指定容量大小

首先明确一点,指定容量大小是为了


  • 减少扩容带来的额外开销
  • 指定容量代销,可以减少无效的内存开销


初始化值设置的关键点:


  • ArrayList: 数据有多少个,初始化值就是多少
  • HashMap: 考虑到扩容因子,初始化大小 = (size / 0.75 + 1)




相关文章
|
9天前
|
Kubernetes 容器 Perl
【赵渝强老师】K8s中Pod中的初始化容器
Kubernetes的Pod包含业务容器、基础容器、初始化容器和临时容器。初始化容器在业务容器前运行,用于执行必要的初始化任务。本文介绍了初始化容器的作用、配置方法及优势,并提供了一个示例。
|
2月前
|
运维 Cloud Native Docker
云原生技术入门:Docker容器化实战
【9月更文挑战第20天】本文将引导你走进云原生技术的世界,通过Docker容器化技术的实战演练,深入理解其背后的原理和应用。我们将一起探索如何在云平台上利用Docker简化部署、扩展和管理应用程序的过程,并揭示这一技术如何改变现代软件的开发和运维模式。
|
1月前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
65 0
|
2月前
|
Linux pouch 容器
CentOS7部署阿里巴巴开源的pouch容器管理工具实战
关于如何在CentOS 7.6操作系统上安装和使用阿里巴巴开源的Pouch容器管理工具的实战教程。
121 2
CentOS7部署阿里巴巴开源的pouch容器管理工具实战
|
1月前
|
Ubuntu Linux 应用服务中间件
Docker容器入门实战
Docker容器入门实战
|
1月前
|
SQL Shell 数据库
在TDengine容器中创建初始化数据库的Shell命令实例
以上就是在Docker容器环境中部署并初始化TDengine数据库的全过程,希望对你有所帮助。
64 0
|
2月前
|
存储 Kubernetes Docker
深入探索容器化技术:Docker 实战与 Kubernetes 管理
深入探索容器化技术:Docker 实战与 Kubernetes 管理
71 0
|
3月前
|
XML Java 数据格式
Spring5入门到实战------8、IOC容器-Bean管理注解方式
这篇文章详细介绍了Spring5框架中使用注解进行Bean管理的方法,包括创建Bean的注解、自动装配和属性注入的注解,以及如何用配置类替代XML配置文件实现完全注解开发。
Spring5入门到实战------8、IOC容器-Bean管理注解方式
|
3月前
|
运维 开发者 Docker
Docker容器部署实战:从入门到精通
【8月更文挑战第31天】 本文将引导读者了解如何使用Docker容器技术来简化和加速应用程序的部署过程。文章将通过实际案例探讨Docker的基本概念、架构,以及如何创建、管理和维护Docker容器。我们将通过详细的代码示例和操作指导,展示如何在本地环境或云基础设施上部署应用,并讨论如何克服在实际部署中可能遇到的挑战。无论你是DevOps工程师、软件开发者还是IT专业学生,本文都将为你提供深入理解并有效使用Docker的全面指南。
|
3月前
|
Kubernetes Cloud Native Docker
云原生入门:Docker容器化部署实战
【8月更文挑战第31天】在数字化浪潮中,云原生技术成为企业转型的助推器。本文通过Docker容器化部署的实践案例,引导读者从零基础到掌握基础的云原生应用部署技能。我们将一起探索Docker的魅力,学习如何将一个应用容器化,并在云平台上运行起来,为深入云原生世界打下坚实基础。