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

来源:互联网 发布:非农数据对贵金属的影响 编辑:程序博客网 时间:2024/06/05 19:55

集合的概念:集合类存放的都是对象的引用,不是对象本身,我们称集合中的对象就是指集合中对象的引用(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. }  
0 0