JavaSE中的集合

JavaSE中的集合结构,常用接口、实现

在这里插入图片描述

底层数据结构

List集合

List集合的主要实现类有ArrayList和LinkedList,分别是数据结构中顺序表和链表的实现
另外还包括栈和队列的实现类:Deque和Queue

ArrayList

  • 在内存中分配连续的空间,实现了长度可变的数组
  • 优点:遍历元素和随机访问元素的效率比较高
  • 缺点:添加和删除需大量移动元素效率低,按照内容查询效率低

LinkedList

  • 采用双向链表存储方式。
  • 缺点:遍历和随机访问元素效率低下
  • 优点:插入、删除元素效率比较高(但是前提也是必须先低效率查询才可。如果插入删除发生在头尾可以减少查询次数)

set集合

无序 唯一(不重复)

HashSet

  • 采用Hashtable哈希表存储结构(神奇的结构)
  • 优点:添加速度快 查询速度快 删除速度快
  • 缺点:无序

LinkedHashSet

  • 采用哈希表存储结构,同时使用链表维护次序
  • 有序(添加顺序)

TreeSet

  • 采用二叉树(红黑树)的存储结构
  • 优点:有序 查询速度比List快(按照内容查询)
  • 缺点:查询速度没有HashSet快

Map集合

特点:存储的键值对映射关系,根据key(唯一)可以找到value

HashMap

  • 采用Hashtable哈希表存储结构(神奇的结构)
  • 优点:添加速度快 查询速度快 删除速度快
  • 缺点:key无序
  • JDK1.7及其之前,HashMap底层是一个table数组+链表实现的哈希表存储结构

LinkedHashMap

  • 采用哈希表存储结构,同时使用链表维护次序
  • key有序(添加顺序)

TreeMap

  • 采用二叉树(红黑树)的存储结构
  • 优点:key有序 查询速度比List快(按照内容查询)
  • 缺点:查询速度没有HashMap快

接口特性

  • Collection 接口存储一组不唯一,无序的对象
  • List 接口存储一组不唯一,有序(索引顺序)的对象
  • Set 接口存储一组唯一,无序的对象
  • Map接口存储一组键值对象,提供key到value的映射
    • Key 唯一 无序
    • value 不唯一 无序

延申

Set|Map集合-Object中常用方法

Set
  add();添加元素,但重复元素不会被添加成功
  contains();判断o是否在集合中
  remove();删除集合中的o
  iterator();返回迭代器
  size();返回set中元素的个数
  clear();清空集合
  isEmpty();检测set是否为空,空返回true,否则返回false
  toArray();将set中的元素转换为数组返回
  addAll();将集合c中的元素添加到set中,可以达到去重效果

Map
  get();返回key对应的value
  put();设置key对应的value
  remove();删除key对应的映射关系
  entrySet();返回所有的key-value映射关系
  keySet();返回所有key的不重复集合
  values();返回所有value的可重复集合
  containsKey();判断是否包含key
  containsValue();判断是否包含value

TreeXxx涉及到排序算法Comparable|Comparetor

内部比较器Comparable—自然排序
外部比较器Comparator—自定义排序

  • 内部比较器Comparable—实现compareTo()方法
  • 外部比较器Comparator—实现compare()方法

  Comparable 提供单个排序序列,而 Comparator 提供多个排序序列

  Comparable 影响原始类,而 comparator 不影响原始类

  对于外部比较器,如果使用次数较少,可以通过匿名内部类来实现。

  需要比较的场合才需要实现内部比较器或者外部比较器,比如排序、比如TreeSet中数据的存储和查询,在HashSet、LinkedHashSet、ArrayList中存储元素,不需要实现内部比较器或者外部比较器。

  如果对象的排序需要基于自然顺序,那么使用 Comparable,而如果你需要对不同对象的属性进行排序,那么在 Java 中使用 Comparator。

ComparableComparator
Comparable 提供 compareTo ()方法对 Java 中的元素进行排序Comparator 提供了 compare ()方法来对 Java 中的元素进行排序
排序逻辑必须在要对其对象进行排序的同一个类中排序逻辑应该在单独的类中,以便根据对象的不同属性编写不同的排序
要对其对象进行排序的类必须实现comparable接口类的对象进行排序,则不需要实现comparator接口
它提供单一排序序列它提供了多种排序序列
该方法可以按照自然排序顺序对数据进行排序该方法根据自定义的排序顺序对数据进行排序
它影响原始类。也就是说,实际类被改变了它不会影响原来的类,也就是说,实际的类不会被改变
经常在 API 中实现实现它是为了对第三方类的实例进行排序
所有包装器类和 String 类都实现了comparable接口唯一实现的比Comparator类是Collator和RuleBasedColator
所有的集合都有数据结构

此处引用Java常见的集合的数据结构,感谢!

Arrays(数组)

  • 查询快:数组的地址是连续的,我们通过数组的首地址可以找到数组,通过数组的索引可以快速查找某一个元素。
  • 增删慢:数组的长度是固定的,我们想要增加/删除一个元素,必须创建一个新数组,把源数组的数据复制过来。
    • 原因:
      • 要把数组中索引是3的元素删除必须创建一个新的数组,长度是源数组的长度-1,
      • 把源数组的其他元素复制到新数组中在新数组的地址赋值给变量ar
      • 源数组会在内存中被销毁(垃圾回收)

LinkedList(链表)

  • 查询慢:链表中地址不是连续的,每次查询元素,都必须从头开始查询。
  • 增删快:链表结构,增加/删除一个元素对链表的整体结构没有影响, 所以增删快。

链表中的每一个元素也称之为一个节点一个节点包含了:

  • 一个数据源(存储数组),两个指针域(存储地址)

单向链表:链表中只有一条链子,不能保证元素的顺序 (存储元素和取出元素的顺序有可能不一致)
双向链表:链表中有两条链子,有一条链子是专门记录元素的顺序,是一个有序的集合

stack(栈)

stack,又称堆栈,它是运算受限的线性表,其限制是仅允许在标的一端进行插入和删除操作,不允许在其他任何位置进行添加、查找、删除等操作。 简单的说:采用该结构的集合,对元素的存取有如下的特点

  • 先进后出(即,存进去的元素,要在后它后面的元素依次取出后,才能取出该元素)。例如:子弹压进弹夹,先压进去的子弹在下面,后压进去的子弹在上面,当开枪时,先弹出上面的子弹,然后才能弹出下面的子弹。
  • 栈的入口、出口的都是栈的顶端位置。

这里两个名词需要注意: 压栈:就是存元素。即,把元素存储到栈的顶端位置,栈中已有元素依次向栈底方向移 动一个位置。 弹栈:就是取元素。即,把栈的顶端位置元素取出,栈中已有元素依次向栈顶方向移动 一个位置

queue(队列)

queue,简称队,它同堆栈一样,也是一种运算受限的线性表,其限制是仅允许在表的一端进行插入,而在表的另一端进行删除

  • 先进先出(即,存进去的。如,小火车过山洞,车头先进去,车尾后进去;车头先出来,车尾后出来

tree(红黑树【二叉树】)

binary tree ,是每个结点不超过2的有序树(tree)

  • 就是一种类似于我们生活中树的结构,只不过每个结点上都最多只能有两个子结点

二叉树是每个节点最多有两个子树的树结构。 顶上的叫根结点,两边被称作“左子树”和“右子树”
二叉树的一种比较有意思的叫做红黑树,红黑树本身就是一颗二叉查找树,将节点插入后,该树仍然是一颗二叉查找树。也就意味着,树的键值仍然是有序的

红黑树

查询的速度非常的快,查询叶子节点最大次数和最小次数不能超过2倍

HashMap(哈希表)

在JDK1.8之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里
但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低
而JDK1.8中,哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间
简单的来说,哈希表是由数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的

Map-Redis

此处引用Map&Redis之间的区别,感谢!

  缓存分为本地缓存和分布式缓存。以java为例,使用自带的map或者guava实现的是本地缓存,最主要的特点是轻量以及快速,生命周期随着jvm的销毁而结束,并且在多实例的情况下,每个实例都需要各自保存一份缓存,缓存不具有一致性。

  使用redis或memcached之类的称为分布式缓存,在多实例的情况下,各实例共用一份缓存数据,缓存具有一致性。缺点是需要保持redis或memcached服务的高可用,整个程序架构上较为复杂。

详细的区别:

  1. Redis 可以用几十 G 内存来做缓存,Map 不行,一般 JVM 也就分几个 G 数据就够大了
  2. vRedis 的缓存可以持久化,Map 是内存对象,程序一重启数据就没了
  3. Redis 可以实现分布式的缓存,Map 只能存在创建它的程序里
  4. Redis 可以处理每秒百万级的并发,是专业的缓存服务,Map 只是一个普通的对象
  5. Redis 缓存有过期机制,Map 本身无此功能
  6. Redis 有丰富的 API,Map 就简单太多了
Queue-MQ

消息队列
“消息队列”消息存储在消息水平传播的容器中。在消息队列管理器中,当将消息从其源传递到其目标时,当中间人。队列的主要用途是提供路由和 securityTransfer 证书消息; 如果收件人无法发送消息,则消息队列消息将保持不变,直到成功传递该消息为止
消息队列中间件是分布式系统的重要组成部分,主要解决应用解耦、异步消息、流量削峰等问题,实现高性能、高可用性、可伸缩的体系结构和最终一致性,是大型系统不可缺少的中间件。

ACK 消息机制
  这个 Ackownledge 消息确认机制,为了确保消息不丢失,消息队列机制提供消息确认,消息队列机制提供消息应答机制,一个消费者消费处理后的确认消息,向消息队列发送一个 ACK 消息队列,消息队列可以删除该消息。如果 消费者关闭/关闭,ACK 没有发送,消息队列没有被处理的消息,消息将再次被发送给其他处理 消费者消费。
同步和异步消息传递
  同步: 以同步方式发送和接收支持的消息。以及另一种同步方式: 同步收发信机场景,消息生产者和消费者双回答模式,例如: 从中继站获得一封给邮局中转站张和约翰多渠道的信,然后写一部分信函收据,进入中转站,然后选择乔史密斯,当然,在他们写座位时有规定的回信地址。如果接收到的消息以同步方式(Pull)接收,如果队列为空,在这种情况下接收同步阻塞状态,它将等待消息到达。
  异步: 收发器也支持异步消息: 发送异步消息,不需要等待接收确认消息队列; 异步接收消息,以一种 Push 消息消费者接收触发消息的方式。

消息队列应用场景

异步处理

现场简介: 用户注册后系统发送注册邮件和短信注册。传统的方式有两种: 并行方式和串行方式
(1)串行方式: 成功注册后,将信息存入数据库,发送文本消息和电子邮件注册,完成三个以上步骤后,将信息成功返回客户端
(2)并行模式: 在数据库中存储的注册信息成功后,同时发送注册短信和电子邮件注册,完成上述三项任务后返回客户端,并行模式下串行模式的区别提高了处理时间

解耦

现场描述: 用户下单后,订单系统需要通知库存系统。传统的方法是接口库存系统的订单系统调用
传统的劣势模式:1)如果库存系统无法访问,减去库存的订单将失效,从而导致订单失败。2)订单系统和库存系统耦合
消息队列程序:订单系统: 订单处理系统完成持久化后,将消息写入消息队列,用户返回成功的单个订单。库存系统: 订购订单信息,采用拉/推方式,获取下单信息,库存信息系统根据订单,库存操作。给定: 在下一个单库存系统不能正常工作。不影响正常的顺序,因为订单系统写消息队列不再关心其他的后续操作。实现订货系统和库存系统的解耦应用

流量削峰

在消息队列的常见场景中,流前端被切断,通常是阻止或集体抢劫,广泛应用于活动中。场景: 流量激增活动,通常是因为流量太大,导致流量激增,应用程序挂起。为了解决这个问题,通常需要在前端应用程序中添加消息队列
1)可以控制活动的数量; 2)短时间内可以缓解应用程序的流量过大
1、用户的请求,服务器接收,先写消息队列。如果队列大小超过最大数量,则直接用户请求放弃或跳转到错误的页面
2、spike服务信息请求消息队列,进行后续处理

Redis底层数据结构(字典)

String(字符串)

在 Redis 中,字符串被称为简单动态字符串,或 SDS。它是 char * 上的一个小包装器,允许您将字符串的长度和空闲字节数作为前缀存储
因为存储了字符串的长度,所以字符串长度是一个 O(1)操作。另外,由于长度已知,Redis 字符串是二进制安全的。字符串包含空字符是完全合法的

字符串是 Redis 最通用的数据结构:

  1. 可以存储文本的字符串
  2. 可以存储二进制数据的字节数组
  3. 可以存储数字的东西
  4. 一个数组或任何其他数据类型),可以允许有效的随机访问
  5. 它允许你设置或获取单独的比特
  6. 可用于构建其他数据结构的内存块。这在内部用于构建 ziplist 和 intset,它们是针对少量元素的紧凑、内存高效的数据结构

Dictionary(字典)

将键映射到其关联值,其中的值可以是字符串、散列、集合、排序集或列表
将密钥映射到其到期时间戳
实现 Hash、Set 和 Sorted Set 数据类型
将 Redis 命令映射到处理这些命令的函数
将 Redis 键映射到该键上阻塞的客户端列表
Redis 字典是使用哈希表实现的
Set数据结构使用字典来保证没有重复

Doubly Linked List(双向链表列表)

列表数据类型是使用双向链表实现的。 Redis的实现直接来自算法教科书。 唯一的变化是Redis将长度存储在列表数据结构中。 这确保了LLEN具有O(1)复杂度

Skip List(跳跃列表)

Redis 使用“跳过列表”作为排序集的基础数据结构
排序集使用跳跃列表和字典。字典存储每个元素的分数

Zip List(压缩列表)

压缩列表就像一个双向链表文件夹,只不过它不使用指针,而是内联存储数据

Int Sets(整形集合)

在 Redis,集合通常使用哈希表来实现。对于较小的集合,哈希表的内存效率很低。当集合仅由整数组成时,数组通常更有效
Int Sets是一个已排序的整数数组。为了找到元素,使用了二进制搜索算法。这具有O(logN)的复杂性。向这个数组添加新整数可能需要重新分配内存,这对于大型整数数组可能会变得非常昂贵
作为进一步的内存优化,Int set有3种不同整数大小的变体:16位、32位和64位。可以根据元素的大小使用正确的变体。当一个新元素被添加,并且它超过了当前的大小,Redis自动迁移它到下一个大小。如果添加了字符串,Redis会自动将Int Sets转换为基于集合的常规哈希表
Int Sets是 CPU 和内存之间的权衡。Int Sets 具有极高的内存效率,对于小集合,它们比哈希表更快。但是在一定数量的元素之后,O(log N) 检索时间和重新分配内存的成本变得太多。根据实验,发现切换到常规哈希表的最佳阈值是 512。但是,您可以根据应用程序的需要增加此阈值(降低它没有意义)

Zip Maps(压缩映射)

Zip Maps 是扁平化并存储在列表中的字典。它们与 Zip Lists 非常相似
自 Redis 2.6 起,Zip Maps 已被弃用,小哈希值存储在 Zip Lists 中

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

week@eight

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值