三大语言(C/Java/Python)基本数据类型大小 / 内置容器 总结

本文总结了C、Java和Python三种语言的基本数据类型大小和内置容器的特点。C语言中,数据类型大小在不同操作系统上有所不同,且直接影响指针操作。Java的所有类型都是有符号的,其容器在JDK1.8+中优化了冲突处理。Python作为弱类型语言,其容器在使用后会被缓存。文章还详细讨论了Java的线程安全容器和Python的哈希策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

三大语言(C/Java/Python)基本数据类型大小 / 内置容器 总结

@Author Luzhuo (http://luzhuo.me/blog)

关于为什么选这三门语言:
Java: 我是做移动开发的, 必选项;
C: 追求极致的速度, C必选;
Python: 快速开发, 不二之选.

基本数据类型

这张表格中, C的字节数大小是最重要的, 因为C能通过指针直接修改某类型的部分值, 而类型大小同时决定了指针的步长.

Java数据类型Java字节数C数据类型C字节数(win32位系统)Python数据类型Python字节数
boolean1bit--bool-
byte1----
char2char1chr-
short2short2--
int4int4int-
long8long4--
--long long8--
float4float4float-
double8double8--
----complex-
string---str-

注:

  1. 以上表格的字节数的单位均为Byte类型, 除非特殊标注, 如1bit
  2. C的基本类型数据字节数比较特殊, 在32位操作系统和62为操作系统上, Win vc12 和 Linux gcc5.3.1 上的表现均不同.
  3. C分为 有符号类型(signed int) 和 无符号类型(unsigned int).
  4. Java的所有类型均为有符号类型.
  5. 1Byte = 8bit, 内存中的数据从右往左看.
  6. Python是弱类型语言, 字节数不是重点, 在C会自动转换数据类型

内置容器

结构组合CJavaPython特点
数组vectorArrayList(Vector/CopyOnWriteArrayList)list动态数组, 查询快O(1),增删慢O(n)
数组+数组deque--双端查询增删都快O(1), 不支持中间段操作
数组+数组stack--FILO(先进后出), 默认使用deque容器, 使用尾部
数组+数组queue--FIFO(先进先出), 默认使用deque容器, 尾部入头部出
数组式二叉树priority_queue--最高级先出, 头部查询快O(1), 增删一般O( log ⁡ 2 N \log_{2}N log2N), 不支持中间段操作, 默认vector容器(实现Heap(完全二叉树)), 尾部入尾部出
链表listLinkedList-双向循环链表, 增删快O(1), 查询慢O(n)
链式二叉树setTreeSet-有序, 不重复, 查询增删都一般O( log ⁡ 2 N \log_{2}N log2N), 使用RBTree容器(链式实现)
链式二叉树multiset--有序, 可重复, 查询增删都一般O( log ⁡ 2 N \log_{2}N log2N), 使用RBTree容器(链式实现)
链式二叉树mapTreeMap-有序, key不重复, 查询增删都一般O( log ⁡ 2 N \log_{2}N log2N), 使用RBTree容器(链式实现)
链式二叉树multimap--有序, key可重复, 查询增删都一般O( log ⁡ 2 N \log_{2}N log2N), 使用RBTree容器(链式实现)
数组+链表hash_setHashSet-无序(Hash分桶), 不重复, 查询增删都慢O(n), 使用HashTable容器(vector+list(桶)实现, 开链法)
数组+链表hash_multiset--无序(Hash分桶), 可重复, 查询增删都慢O(n), 使用HashTable容器(vector+list(桶)实现, 开链法)
数组+链表hash_mapHashMap(Hashtable/ConcurrentHashMap)-无序(Hash分桶), key不重复, 查询增删都慢O(n), 使用HashTable容器(vector+list(桶)实现, 开链法)
数组+链表hash_multimap--无序(Hash分桶), key可重复, 查询增删都慢O(n), 使用HashTable(vector+list(桶)实现, 开链法)
-----
数组-(Stack)-FILO(先进后出), 增删查尾部都快O(1), 不支持中间段操作, 默认使用(Vector)容器, 使用尾部
数组-ArrayDeque-双端数组, 增删查头尾指针都快O(1), 不支持中间段操作, 添加元素时头尾指针分别往中间夹
数组*2-EnumMap-双数组, 分别存key,value, 增删查都快O(1), key必须为枚举类型
数组-IdentityHashMap-数组, 增删查较快O(k), key, value分别在+0, +1位置
数组+链表-LinkedHashMap-插入顺序 / 访问顺序(LRU), 在HashMap的Node上多加两个指针, 形成双向循环链表保证元素有序, LRU访问将结点移至链尾
数组+链表-LinkedHashSet-插入顺序, 直接使用LinkedHashMap
数组+链表-WeakHashMap-插入顺序, key无引用将自动GC, 使用HashTable实现
链式SkipList-(ConcurrentSkipListMap)-有序, key不重复, 增删查一般O( log ⁡ 2 N \log_{2}N log2N), CAS, 并发安全, 使用SkipList实现(链式), 可代替TreeMap的安全并发
链式SkipList-(ConcurrentSkipListSet)-有序, 直接使用 ConcurrentSkipListMap, 可代替TreeSet的安全并发
数组-(CopyOnWriteArraySet)-插入顺序, 增删查都慢O(n), 直接使用CopyOnWriteArrayList, 可代替HashSet的安全并发
链表-(ConcurrentLinkedDeque)-双向循环链表, 顶部增删查O(1), 不支持中间段访问, CAS, 可代替ArrayDeque的安全并发
链表-(LinkedTransferQueue)-单向循环链表, SynchronousQueue(直接给) + LinkedBlockingQueue(有缓冲队列), 并发安全的队列
数组-(ArrayBlockingQueue)-循环数组, 容量很小, 有缓冲区, 并发安全的队列
链表-(LinkedBlockingQueue)-单向循环链表, 容量很大, 有缓冲区, 并发安全的队列
数组式二叉树-PriorityQueue(PriorityBlockingQueue)heapq(queue.PriorityQueue)最低级先出, 增删一般O( log ⁡ 2 N \log_{2}N log2N), 动态(Heap完全二叉树)数组, 有缓冲区, 尾入头出, 并发安全
数组式二叉树-(DelayQueue)-可延迟的队列, 直接使用PriorityQueue, 并发安全(ReentrantLock)的队列
--(SynchronousQueue)-无缓冲的队列, 直接放直接给, 并发安全的队列
-----
数组--dict无序, key不重复, 增删查O(k), 使用HashTable, 开放定址法
数组--set无序, key不重复, 增删查O(k), 使用HashTable, 开放定址法
数组--tuple原序, 容量不变, 查O(1), 不支持增改
链表--(deque)双向循环链表, 增删O(1), 查O(n), 线程安全, 充当队列
链表--(queue.Queue)FIFO(先进先出)队列, 直接使用deque, 尾入头出
数组--(queue.LifoQueue)LIFO(后进先出)队列, 直接使用list, 使用尾部

Java中非线程安装的结构可转为线程安全的结构

Map<E> map = Collections.synchronizedMap(new HashMap<E>());
List<E> list = Collections.synchronizedList(new ArrayList<E>());

Java并发替代容器

非并发容器并发容器安全原理
ArrayListCopyOnWriteArrayListReentrantLock + arraycopy
ArrayDequeConcurrentLinkedDequeCAS(sun.misc.Unsafe)
TreeMapConcurrentSkipListMapSkipList的CAS(sun.misc.Unsafe)
TreeSetConcurrentSkipListSet直接使用 ConcurrentSkipListMap
HashMapConcurrentHashMap分段锁(synchronized加在hash元素对象上)
HashSetCopyOnWriteArraySet直接使用CopyOnWriteArrayList, 去重由(遍历O(n)所有元素, 存在则不添加)实现

Java的队列

结构组合Java特点
数组式二叉树PriorityQueue(PriorityBlockingQueue)优先级队列
链表(LinkedTransferQueue)高效率队列, SynchronousQueue+LinkedBlockingQueue
数组(ArrayBlockingQueue)循环数组队列(容量小)
链表(LinkedBlockingQueue)单向循环链表队列(容量大)
数组式二叉树(DelayQueue)可延迟的队列, 直接使用PriorityQueue
-(SynchronousQueue)无缓冲的队列

注:

  1. priority_queue为什么不是头部出, 因为要被删除的元素先被移到尾部, 再弹出,
  2. HashTable的增删查为什么不是O(1), 因为发生hash碰撞就是O(n)
  3. Java()内的结构为同步结构, 也就是线程安全的.
  4. JDK1.8+会将与HashTable相关容器的链表, 在过长时会转为RBTree
  5. HashSet直接使用HashMap来存储key, TreeSet直接使用TreeMap来存储key, 所以可认为他们分别为同一个东西.
  6. LinkedHashSet虽然直接使用LinkedHashMap来存储key, 但并未启用LRU (dummy占位)
  7. WeakHashMap的特性非常适合做缓存, 无引用将被自动GC.
  8. 分段锁, 对hash数组分段的锁, 实现的线程安全比原始线程安全的效率高, 比如ConcurrentHashMap比Hashtable效率高. (JDK1.8不再分段, 直接对hash元素加锁)
  9. 注意Java的容器Hashtable(小写的t)和结构HashTable(大写的T)的区别.
  10. 优先队列, C++的priority_queue最高级先出, Java的PriorityQueue最低级先出.
  11. EnumMap 的数组为什么增删查都是O(1)呢? 因为key数组按key值索引添加, value值按key值增加, 删除将value置为null, key保留, 不存在移动, 查询按key值查.
  12. IdentityHashMap, 一个数组同时存放key,value, key放在偶数位, value放在奇数位, hash碰撞看key的内存地址值, 相同覆盖, 不同将hash+2; 删除, 将key,value置为null
  13. Python的容器, 不管是list, dict, 还是tuple 等等, 用完之后都会缓存起来以备下次使用, 而不是销毁.
  14. 开放定址法: 在hash的基础上再hash.
  15. 再哈希法: 根据key使用不同的哈希函数生成多个hash.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值