对构建hashSet集合的几点见解

[size=medium][/size][color=blue][/color]
最近自己做了一类似于hashSet集合的小程序。该程序通过模仿法hashSet特征,同时也根据自己的一些需要自定义了一些格式内容放里面,实现了add()、search()、remove()等方法。好啦 !废话就少说啦,下面是我对hashSet的一些总结。欢迎各位大侠指点。。。

1.    HashSet概述:
   HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持。它不保证set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用null元素。
 
2.    HashSet的实现:
   对于HashSet而言,它是基于HashMap实现的,HashSet底层使用HashMap来保存所有元素,因此HashSet 的实现比较简单,相关HashSet的操作,基本上都是直接调用底层HashMap的相关方法来完成, HashSet的源代码如下:
Java代码 
 public class HashSet<E>  
     extends AbstractSet<E>  
     implements Set<E>, Cloneable, java.io.Serializable  
 {  
     static final long serialVersionUID = -5024744406713321676L;  
  
     // 底层使用HashMap来保存HashSet中所有元素。  
     private transient HashMap<E,Object> map;  
       
     // 定义一个虚拟的Object对象作为HashMap的value,将此对象定义为static final。  
     private static final Object PRESENT = new Object();  
  
     /** 
      * 默认的无参构造器,构造一个空的HashSet。 
      *  
      * 实际底层会初始化一个空的HashMap,并使用默认初始容量为16和加载因子0.75。 
      */ 
     public HashSet() {  
     map = new HashMap<E,Object>();  
     }  
  
     /** 
      * 构造一个包含指定collection中的元素的新set。 
      * 
      * 实际底层使用默认的加载因子0.75和足以包含指定 
      * collection中所有元素的初始容量来创建一个HashMap。 
      * @param c 其中的元素将存放在此set中的collection。 
      */ 
     public HashSet(Collection<? extends E> c) {  
     map = new HashMap<E,Object>(Math.max((int) (c.size()/.75f) + 1, 16));  
     addAll(c);  
     }  
  
     /** 
      * 以指定的initialCapacity和loadFactor构造一个空的HashSet。 
      * 
      * 实际底层以相应的参数构造一个空的HashMap。 
      * @param initialCapacity 初始容量。 
      * @param loadFactor 加载因子。 
      */ 
     public HashSet(int initialCapacity, float loadFactor) {  
     map = new HashMap<E,Object>(initialCapacity, loadFactor);  
     }  
  
     /** 
      * 以指定的initialCapacity构造一个空的HashSet。 
      * 
      * 实际底层以相应的参数及加载因子loadFactor为0.75构造一个空的HashMap。 
      * @param initialCapacity 初始容量。 
      */ 
     public HashSet(int initialCapacity) {  
     map = new HashMap<E,Object>(initialCapacity);  
     }  
  
3.以上是我参考了hashSet 源代码再结合自己的一些经验给出的几点看法。下面是我这次对hashSet的亲身体验:
/**
 * 主类  用来处理各种哈希事件
 * @author
 *
 */
public class HashMain {
 //定义一个具有初始长度的数组
 private  InfoNode[]  nodeArray = new InfoNode[300];
 public static int sum = 100;
 /**
  *  add()方法  添加用户
  */
 public void add(int i ,InfoNode node){
  int index = hashFuction(i);
  if(nodeArray[index]==null){//如果该索引位置的数组值为空
   nodeArray[index]=node;
  }else{
   InfoNode root = nodeArray[index];//根节点
   InfoNode next = root.getChild();//此时根节点的下一个节点
   root.setChildNode(node);//设置当前节点为子节点
   node.setFatherNode(root);
   if(next!=null){
    //root.getChild().setChildNode(next);
    node.setChildNode(next);
    next.setFatherNode(node);
   }
  }
 }
 /**
  * 定义一个查找用户的方法(根据用户名字)
  */
 public UserInfo search(String name){
  for(int i=0;i<nodeArray.length;i++){
   InfoNode root = nodeArray[i];
   if(root==null) continue;//如果该数组元素为空 则直接进入下一个循环
   while(root!=null){
    if(root.getInfo().getName().equals(name)){
     return root.getInfo();
    }
    root = root.getChild();
   }

  }
  return null;
 }
 /**
  * 重载一个查找用户的方法(根据编号)
  */
 public UserInfo search(int number){
  int index = hashFuction(number);//获得该元素在数组中的索引
  InfoNode root = nodeArray[index];
  while(root!=null){
   if(root.getInfo().getNum()==number){
    return root.getInfo();
   }
  }
  return null;
 }
 /**
  * 定义删除某一个用户的方法(根据该用户的名字)
  */
 public void remove(String name){
  for(int i=0;i<nodeArray.length;i++){
   InfoNode root = nodeArray[i];
   if(root==null) continue;//如果数组元素为空 则直接进行下一次循环
   //如果数组本省的元素就是要找的用户的话
   if(root.getInfo().getName().equals(name)){
    InfoNode next = root.getChild();
    if(next!=null){
     nodeArray[i]=next;
     System.out.println("删除了名为"+name+"的学生,该学生人气指数为:"+root.getInfo().getNum());
     break;
    }else{
     nodeArray[i]=null;
     System.out.println("删除了名为"+name+"的学生,该学生人气指数为:"+root.getInfo().getNum());
     break;
    }
   }
   //遍历整个数组以及数组中原所包含的所有节点
   while(root!=null){
    String userName = root.getInfo().getName();
    if(userName.equals(name)){
     InfoNode child = root.getChild();
     InfoNode father = root.getFather();
     if(child!=null){//如果当前root不是最后一个节点
      father.setChildNode(child);
      child.setFatherNode(father);
     }else{//如果当前root是链表末尾节点
      father.setChildNode(null);
     }
     System.out.println("删除了名为"+name+"的学生,该学生人气指数为:"+root.getInfo().getNum());
     break;
    }
    root = root.getChild();
   }
  }
 }
 /**
  * 哈希函数
  */
 public int hashFuction(int i){
  int index = i%(nodeArray.length-1);
  return index;

 }
 /**
  * 定义重建哈希集合的方法
  */
 public void reSetHash(){
  InfoNode[] reNodeArray = new InfoNode[sum];
  nodeArray = reNodeArray;//,新建一个数组指向原来的数组
  init();
 }
 /**
  * 打印数组的方法
  */
 public int printArray(){
  int count1=0;
  int count2=0;
  for(int i=0;i<nodeArray.length;i++){
   InfoNode nextNode = nodeArray[i];
   //遍历整个数组以及数组中原所包含的所有节点
   while(nextNode!=null){
    String name = nextNode.getInfo().getName();
    int number = nextNode.getInfo().getNum();
    System.out.println(name+"的人气指数是:"+number);
    nextNode = nextNode.getChild();
    count1++;
   }
   //遍历数组本身的元素
   if(nodeArray[i]!=null){
    count2++;
   } 
  }
  return count1-count2;//返回幅值
 }
 /**
  * 初始化数组
  * @param userArray
  */
 public void init(){
  for(int i=0;i<sum;i++){//循环创建用户对象
   int number = (int)(Math.random()*400);//产生随机数
   String name = "学生"+String.valueOf(i);
   UserInfo user = new UserInfo(number,name);
   InfoNode node = new InfoNode(user);
   add(number,node);//向数组中添加元素
  }

 }
 /**
  * 主类
  * @param args
  */
 public static void main(String[] args) {
  HashMain hash = new HashMain();
  hash.init();
  //***********************建立hash集合
  int count = hash.printArray();
  System.out.println("幅值为"+count);
  
  //***********************删除某个元素
  hash.remove("学生49");
  
  //***********************根据用户名查找某个元素(遍历查找)
  int time = (int) System.currentTimeMillis();
  UserInfo user = hash.search("学生56");
  int last = ((int) System.currentTimeMillis()-time)*1000;
  if(user!=null){
  System.out.println("查找到了"+user.getName()+"该学生的人气指数是:"+user.getNum()+"用时"+last);
  }else{
   System.out.println("该hash集合中没有要查找的元素!");
  }
  
  //***********************根据编号查找某个元素(索引查找)
  int time2 = (int) System.currentTimeMillis();
  UserInfo user2 = hash.search(278);
  int last2 = ((int) System.currentTimeMillis()-time2)*1000;
  if(user2!=null){
  System.out.println("查找到了"+user2.getName()+"该学生的人气指数是:"+user2.getNum()+"用时"+last2);
  }else{
   System.out.println("该hash集合中没有要查找的元素!");
  }
  
  //如果链表元素的数目太多则重建hash
  if(count>sum*(1.25)){
   hash.reSetHash();
   System.out.println("重建了hash集合!!!");
  }
 }
}

这是hashSet的主类,这段代码里面还包含大家最熟悉的InfoNode(用户节点类),以及UserInfo(用户类,即用户节点类的数据域),在这里就不再罗嗦了 :) 。

 


   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ArrayList和HashSet都是Java中常用的集合类。ArrayList是一个动态数组,可以根据需要自动扩展容量,而HashSet一个基于哈希表的集合,它不允许重复元素,可以用于去重。下面是它们的一些特点和常用方法: ArrayList: - 可以存储重复元素,可以根据下标访问元素。 - 添加元素使用add()方法,删除元素使用remove()方法,获取元素使用get()方法。 - 可以使用for循环或者迭代器遍历元素。 - 底层实现是一个数组,当数组容量不足时会自动扩容。 HashSet: - 不允许存储重复元素,可以用于去重。 - 添加元素使用add()方法,删除元素使用remove()方法,查询元素使用contains()方法。 - 可以使用for循环或者迭代器遍历元素。 - 底层实现是一个哈希表,当元素数量过多时会自动扩容。 下面是一个示例代码,演示了如何使用ArrayList和HashSet: ```java import java.util.ArrayList; import java.util.HashSet; public class Main { public static void main(String[] args) { // 创建一个ArrayList ArrayList<String> arrayList = new ArrayList<>(); // 添加元素 arrayList.add("apple"); arrayList.add("banana"); arrayList.add("orange"); // 遍历元素 for (String fruit : arrayList) { System.out.println(fruit); } // 创建一个HashSet HashSet<String> hashSet = new HashSet<>(); // 添加元素 hashSet.add("apple"); hashSet.add("banana"); hashSet.add("orange"); hashSet.add("apple"); // 添加重复元素 // 遍历元素 for (String fruit : hashSet) { System.out.println(fruit); } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值