集合的概念及应用和HashSet保证数据不重复的原理

集合的概念:集合类存放的都是对象的引用,不是对象本身,我们称集合中的对象就是指集合中对象的引用(reference),存放在Java.util包中。

集合类型主要有3种:set(集)、list(列表)和map(映射)。

集合的特点是:可以改变长度,但不保证迭代顺序和不存放重复的数据

在集合中如何判断两个数据相等?

在集合中判断一个数据是否相等要根据它的HashCode方法和equlas方法来判断内容是否相等,我们在判断一个数据是否相等的时候,首先它会调用自己的HashSet方法计算出一个Code值,然后通过这个code值来找到数据在集合中的位置,如果code值的位置上没有数据就将这个数据存放在集合中,如果有,就调用equals方法比较两个数据的大小,如果相等就返回true,否则返回false,如果返回的是true就说明集合中已经有一个数据和你要存放的数据相等了,那就不要再将这个数据存放进去,HashSet不能存放两个相同的数据,如果你一定要将这个数据存入集合就要重写HashCode方法equals方法,因为怕和集合中的数据产生重复,如果重复了你不重写这两个 方法是不能放进去的(ps:一定要HashCode方法和equals方法都相等才能说数据相等,二者缺一不可)

下面是一些代码下载的实现:

向集合中存储数据

Java代码  

  1. /**
  2. * 增加数据的方法
  3. *
  4. * @param e
  5. */
  6. public void add(E e) {
  7. Node<E> node = new Node<E>(e);// 创建一个新结点并指定数据
  8. // 如果head指向的数据为空说明是一个空链表
  9. if (head == null) {
  10. head = node;// 那么将head指向node
  11. last = node;// last也指向node,这时node即是头结点 也是尾结点
  12. num++;// 结点数增加
  13. } else {
  14. // 如果head不为空说明链表中有数据,调用isDuplicate方法,看要添加的数据和链表中的数据是否重复
  15. boolean bool = isDuplicate(node);
  16. if (!bool) {
  17. // 根据node的hashcode值找到下标
  18. int index = getIndex(node.code);
  19. // 调用insert方法,将数据插入在index位置
  20. insert(index, e);
  21. num++;// 结点数增加
  22. }
  23. }
  24. }

向集合中添加数据的时候调用插入方法在这里面对数据进行比较

Java代码 下载 

  1. /**
  2. * 定义一个私有的插入方法
  3. *
  4. * @param index插入结点的下标
  5. * @param e插入的内容
  6. */
  7. private void insert(int index, E e) {
  8. Node<E> node = new Node<E>(e);// 创建新结点并指定数据
  9. // 插入的结点位置是头结点的位置
  10. if (index == 0) {
  11. node.next = head;// 将node的下一个结点指向head
  12. head.front = node;// head的上一个结点指向node
  13. head = node;// 将head指向 node,这时node中的数据处于第一个head的位置
  14. }
  15. // 其他位置
  16. else {
  17. // 创建一个新结点,调用getNode(index)方法找到我们要插入数据的结点的位置
  18. Node<E> n1 = getNode(index);
  19. Node<E> n2 = n1.front;// 再创建一个结点,将我们找到n1位置的上一个结点指向n2
  20. // 将node插在n2和n1的中间,n2->node->n1,所以
  21. n2.next = node;// n2的下一个结点指向node
  22. node.front = n2;// node的上一个结点 指向n2
  23. node.next = n1;// node的下一个结点指向n1
  24. n1.front = node;// n1的上一个结点指向node
  25. // 上面这一操作主要是在n2和n1的中间插入node结点,必须得改变他们的指向关系
  26. }
  27. }

获取数据的方法

Java代码 下载 

  1. /**
  2. * 取出并移除一个数据
  3. *
  4. * @return返回取出数据的内容
  5. */
  6. public E get() {
  7. // 看头结点是否为空,不为空才继续下面的操作否则返回null
  8. if (head != null) {
  9. Node<E> n = head;// 定义一个新结点指向head
  10. head = head.next;// 将head指向它的下一个结点
  11. n.next = null;// 将新结点n的下一个结点指向null
  12. num--;
  13. return n.data;// 返回原来head的值
  14. }
  15. return null;
  16. }

删除数据提供了两种不同的方法

①根据下标删除数据

Java代码  

  1. /**
  2. * 根据下标删除数据
  3. *
  4. * @param index要删除数据的下标
  5. */
  6. public void delete(int index) {
  7. Node<E> n = getNode(index);//创建一个新结点并根据下标获取需要删除的数据的位置
  8. //三者的位置n1->n->n2
  9. Node<E> n1 = n.front;//n1指向n的前一个结点
  10. Node<E> n2 = n.next;//n2指向n的下一个结点
  11. //下面将实现删除n结点
  12. n2.front = n1;
  13. n1.next = n2;
  14. n.front = null;
  15. n.next = null;
  16. num--;
  17. }

②根据内容删除数据

Java代码下载  

  1. /**
  2. * 根据内容删除数据的方法
  3. *
  4. * @param e
  5. */
  6. public void delete(E e) {
  7. Node<E> node = head;//创建新结点指向head
  8. int code = e.hashCode();//获得结点e的hashCode值
  9. while (node != null) {//node结点指向的数据不为null,进入循环
  10. //判断node的hashCode和内容是否等于e的hashCode和内容,相等就获取node的下标调用根据下标删除内容的方法
  11. if (node.data.equals(e) && node.code == code) {
  12. int m = getIndex(node.code);
  13. delete(m);
  14. }
  15. node = node.next;
  16. }
  17. }

判断集合中是否有结点数据与要添加的数据相同的数据

Java代码  

  1. /**
  2. * 判断集合中是否有结点数据与要添加的数据相同的数据
  3. *
  4. * @param node要添加的数据
  5. * @return如果相同返回ture,没有相同的就返回false
  6. */
  7. private boolean isDuplicate(Node<E> node) {
  8. Node<E> n = head;// 定义一个新结点指向head
  9. // 如果n指向的结点数据不为空就赶进入循环
  10. while (n != null) {
  11. // 判断n所指向 的数据和传入的数据的内容和code值 是否相等,相等返回true,否则n指向下一个结点
  12. if (n.data.equals(node.data) && n.code == node.code) {
  13. return true;
  14. }
  15. n = n.next;
  16. }
  17. return false;
  18. }

根据结点的hashcode值计算出结点的位置

Java代码  

  1. /**
  2. * 根据结点的hashcode值计算出结点的位置
  3. *
  4. * @param code
  5. *            结点的hashcode值
  6. * @return返回结点的位置
  7. */
  8. private int getIndex(int code) {
  9. int t = -1;// 定义一个变量t给它赋值为一个不存在的值
  10. Node<E> node = head;// 定义一个新的结点指向head
  11. // 如果Node所指向结点的数据不为null,就进入循环
  12. while (node != null) {
  13. t++;// 这时变量t增加
  14. // 如果node的hashcode值大于等于我们要查找的数据的hashcode就退出循环,否则指向下一个结点
  15. if (node.code >= code) {
  16. break;
  17. }
  18. node = node.next;
  19. }
  20. return t;
  21. }

根据下标确定结点

Java代码  

  1. /**
  2. * 根据下标确定结点
  3. *
  4. * @param index查找结点的下标
  5. * @return返回的结点的内容
  6. */
  7. private Node<E> getNode(int index) {
  8. int t = -1;// 定义一个变量赋值为一个不存在的值
  9. // 判断我们在查找的下标是否在结点数范围内
  10. if (index >= 0 && index < num) {
  11. Node<E> node = head;// 创建新结点指向head
  12. // 如果node结点所指向的数据不为空就进入循环
  13. while (node != null) {
  14. // 这时t增加到0,从下标的最小值,如果前面定义的时候从0开始,这时再增加t就已经不再是下标的最小值,就和我们需要的结点对不上
  15. t++;
  16. // 如果t和Index相等就说明找到就退出程序,否则指向下一个结点继续循环
  17. if (t == index) {
  18. break;
  19. }
  20. node = node.next;
  21. }
  22. return node;
  23. } else {
  24. // 抛出异常
  25. throw new IndexOutOfBoundsException("下标超出边界!index:" + index + ",size:" + num);
  26. }
  27. }
  28. }
时间: 2024-10-08 11:41:29

集合的概念及应用和HashSet保证数据不重复的原理的相关文章

Kafka在高并发的情况下,如何避免消息丢失和消息重复?kafka消费怎么保证数据消费一次?数据的一致性和统一性?数据的完整性?

1.kafka在高并发的情况下,如何避免消息丢失和消息重复? 消息丢失解决方案: 首先对kafka进行限速, 其次启用重试机制,重试间隔时间设置长一些,最后Kafka设置acks=all,即需要相应的所有处于ISR的分区都确认收到该消息后,才算发送成功 消息重复解决方案: 消息可以使用唯一id标识 生产者(ack=all 代表至少成功发送一次) 消费者 (offset手动提交,业务逻辑成功处理后,提交offset) 落表(主键或者唯一索引的方式,避免重复数据) 业务逻辑处理(选择唯一主键存储到R

Python 集合set概念和操作

# 集合 # 概念 # 无序的, 不可随机访问的, 不可重复的元素集合 # 与数学中集合的概念类似,可对其进行交.并.差.补等逻辑运算 # 分为可变集合和非可变集合 # set # 为可变集合 # 增 # 删 # 改 # frozenset # 不可变集合 # 创建好之后, 无法增删改 # 定义 # 可变集合set # s = {1,2,3,4} # s = set(iterable) # 其中iterable可以是字符串.列表.元组.字典等 # 但是为dict时,只会获取提Key作为set的元

volatile足以保证数据同步吗

上一节已经了解了java内存模型,JMM为了提高执行性能,引入了工作内存和主存两个概念,在继续讨论之前必须先搞清四种存储介质:寄存器.高级缓存.RAM和ROM. RAM与ROM大家都比较熟悉了,可以看成是我们经常说的内存与硬盘,寄存器属于处理器里面的一部分,而高级缓存cache是CPU设计者为提高性能引入的一个缓存,也可以说是属于处理器的一部分.在利用CPU进行运算时必定涉及操作数的读取,假如CPU直接读取ROM,那么这个读取速度简直是无法忍受的,于是引入了内存RAM,这样做确实让速度提高了很多

【转】Java 集合系列04之 fail-fast总结(通过ArrayList来说明fail-fast的原理、解决办法)

概要 前面,我们已经学习了ArrayList.接下来,我们以ArrayList为例,对Iterator的fail-fast机制进行了解.内容包括::1 fail-fast简介2 fail-fast示例3 fail-fast解决办法4 fail-fast原理5 解决fail-fast的原理 转载请注明出处:http://www.cnblogs.com/skywang12345/p/3308762.html 1 fail-fast简介 fail-fast 机制是java集合(Collection)中

[转帖]kafka 如何保证数据不丢失

https://www.cnblogs.com/MrRightZhao/p/11498952.html 一般我们在用到这种消息中件的时候,肯定会考虑要怎样才能保证数据不丢失,在面试中也会问到相关的问题.但凡遇到这种问题,是指3个方面的数据不丢失,即:producer consumer 端数据不丢失  broker端数据不丢失下面我们分别从这三个方面来学习,kafka是如何保证数据不丢失的 一.producer 生产端是如何保证数据不丢失的 1.ack的配置策略 acks = 0 生产者发送消息之

Java中的Set集合接口实现插入对象不重复的原理

在java的集合中,判断两个对象是否相等的规则是: 1).判断两个对象的hashCode是否相等 .      如果不相等,认为两个对象也不相等,完毕       如果相等,转入2)(这一点只是为了提高存储效率而要求的,其实理论上没有也可以,但如果没有,实际使用时效率会大大降低,所以我们这里将其做为必需的.后面会重点讲到这个问题.) 2).判断两个对象用equals运算是否相等 .      如果不相等,认为两个对象也不相等       如果相等,认为两个对象相等(equals()是判断两个对象

Spark Streaming使用Kafka保证数据零丢失

来自: https://community.qingcloud.com/topic/344/spark-streaming使用kafka保证数据零丢失 spark streaming从1.2开始提供了数据的零丢失,想享受这个特性,需要满足如下条件: 数据输入需要可靠的sources和可靠的receivers 应用metadata必须通过应用driver checkpoint WAL(write ahead log) 可靠的sources和receivers spark streaming可以通过

第二十节,基本数据类型,集合set、综合应用新数据更新老数据

基本数据类型,集合set.综合应用新数据更新老数据 创建两个字典新数据,更新原始数据,a为原始数据,b为新数据 1,分别获取到a字典和b字典的key(键),将两个字典的键分别转换成两个集合 2,找出a2集合里存在,b2集合里不存在的元素,得到:{'#2', '#3'}(需要删除:?) 3,找出b2集合里存在,a2集合里不存在的元素,得到:{'#4', '#7'}(需要新建:?) 4,找出a2集合和b2集合有交集的元素,也就是a2集合和b2集合都存在的元素,得到:{'#1'}(需要更新:?) 5,

三级级联查询省份名称和编码(保证名称不重复)的SQL语句

1.省份.地市和县级数据库表 2.SQL语句 SELECT DISTINCT t.`province_name`,t.`province_code` FROM t_area_tab t 3.查询结果 4.说明 (1)这个SQL语句保证省份名称和编码不重复 (2)省份和省份编码一 一对应 三级级联查询省份名称和编码(保证名称不重复)的SQL语句