Java集合框架(1)hashset
来源:互联网 发布:vmware mac os 慢 编辑:程序博客网 时间:2024/05/16 09:13
众所周知,hashset里面存储的元素都具有无序性,标识唯一性。但最近仔细研究了一下java里面的hashset,发现hashset里面大多数的内容都是在hashmap的基础上进行修改的。
接下来是hashset的源码展示:
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable{ static final long serialVersionUID = -5024744406713321676L; private transient HashMap<E,Object> map; // Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object(); public HashSet() { map = new HashMap<>(); } public HashSet(Collection<? extends E> c) { map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); addAll(c); } public HashSet(int initialCapacity, float loadFactor) { map = new HashMap<>(initialCapacity, loadFactor); } public HashSet(int initialCapacity) { map = new HashMap<>(initialCapacity); } HashSet(int initialCapacity, float loadFactor, boolean dummy) { map = new LinkedHashMap<>(initialCapacity, loadFactor); } public Iterator<E> iterator() { return map.keySet().iterator(); } public int size() { return map.size(); } public boolean isEmpty() { return map.isEmpty(); } public boolean contains(Object o) { return map.containsKey(o); } public boolean add(E e) { return map.put(e, PRESENT)==null; } public boolean remove(Object o) { return map.remove(o)==PRESENT; } public void clear() { map.clear(); } public Object clone() { try { HashSet<E> newSet = (HashSet<E>) super.clone(); newSet.map = (HashMap<E, Object>) map.clone(); return newSet; } catch (CloneNotSupportedException e) { throw new InternalError(); } } private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { // Write out any hidden serialization magic s.defaultWriteObject(); // Write out HashMap capacity and load factor s.writeInt(map.capacity()); s.writeFloat(map.loadFactor()); // Write out size s.writeInt(map.size()); // Write out all elements in the proper order. for (E e : map.keySet()) s.writeObject(e); } private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { // Read in any hidden serialization magic s.defaultReadObject(); // Read in HashMap capacity and load factor and create backing HashMap int capacity = s.readInt(); float loadFactor = s.readFloat(); map = (((HashSet)this) instanceof LinkedHashSet ? new LinkedHashMap<E,Object>(capacity, loadFactor) : new HashMap<E,Object>(capacity, loadFactor)); // Read in size int size = s.readInt(); // Read in all elements in the proper order. for (int i=0; i<size; i++) { E e = (E) s.readObject(); map.put(e, PRESENT); } }}
静下心来仔细研究了一下,发现hashset是通过将相应的内容存储在了一个hashmap里的key中,然后再去读取的。
在对于hashset进行遍历的时候,主要有两种方式:
第一种是在jdk1.5之前才出现的方式:
import java.util.ArrayList;import java.util.Collection;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.LinkedHashSet;import java.util.Map;import java.util.Map.Entry;import java.util.Set;public class set { public static void main(String [] args) { /*对于hashset里面的排序其实也并不是完全没有顺序的,它实际上是按照hashcode来决定的*/ System.out.println("-----set1 iterator遍历------"); Set<String> set=new HashSet<String>(); set.add("a"); set.add("b"); set.add("c"); set.add("d"); Iterator<String> iterator=set.iterator(); String str=null; while(iterator.hasNext()) { str=iterator.next(); System.out.println(str); } }}
第二种遍历方式是在jdk1.5以后才出现的foreach循环
package Java_Collection_FrameWork;import java.util.ArrayList;import java.util.Collection;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.LinkedHashSet;import java.util.Map;import java.util.Map.Entry;import java.util.Set;public class set { public static void main(String [] args) { /*对于hashset里面的排序其实也并不是完全没有顺序的,它实际上是按照hashcode来决定的*/ System.out.println("-----set1 iterator遍历------"); Set<String> set=new HashSet<String>(); set.add("a"); set.add("b"); set.add("c"); set.add("d"); for (String string : set) { System.out.println(string); } }}
二者的遍历速度相比而言,foreach循环遍历更加的快。原因也很简单,因为第一种的方式不仅要把hashset先通过迭代器去读取,接着还要从hashmap里面去读取Entry的值。然而在foreach循环里面,对于hashset的遍历则是直接的将hashmap的Entry和value值给读取了出来。
谈到这个时候,也许我们会有些好奇,如果hashset里面将相应的内容都存在了一个hashmap的key里面进行保存,那么hashmap的value又会被用来存储什么呢?
在hashset的源码里面,对于其传过来的数值,会被保存到相应的hashmap的key里面,相对应的value则会用于保存一个叫做PRESENT的静态对象。
在hashset里面,每个被存储进来的数值排序都是按照相对应的hashcode进行一定的划分的。对于hashcode用于存储对象的内容,在这里我不打算细讲,可以推荐各位去阅读下列的相应文章,里面的内容写的相当详细。
http://blog.csdn.net/fenglibing/article/details/8905007
那么在hashset里面存储的对象又是怎么进行判断的呢?
在这里附上一小段代码来演示:
class demo{ public String key; public String value; public demo(String key,String val) { this.key=key; this.value=val; } public String toString() { return "demo[key:"+key+", value:"+value+"]"; }}public class hashset02 { public static void main(String[] arg) { demo d1=new demo("02","haha"); demo d2=new demo("02","haha"); Set<demo> set=new HashSet<demo>(); set.add(d1); set.add(d2); System.out.println(d1.hashCode()); System.out.println(d2.hashCode()); System.out.println(set.contains(new demo("02","haha"))); }}
其输出的结果是:
18790965081080497174false
前两行输出的结果不一样还好理解,但是为什么到了第三行会输出一个false呢?其实真正的判断两个对象是否想的的时候,是需要通过hashcode和equals方法进行判断的。于是我对于这个hashcode和equal方法进行了相对应的重写:
class demo{ public String key; public String value; public demo(String key,String val) { this.key=key; this.value=val; } public boolean equals(Object e) { if(e==this) { return true; } /*判断是否是同一个类*/ if(e.getClass()==demo.class) { demo d=(demo) e; return this.key.equals(d.key)&&this.value.equals(d.value); } return false; } public int hashCode() { return key.hashCode(); } public String toString() { return "demo[key:"+key+", value:"+value+"]"; }}
此时返回的结果就是true了(如下方结果所示)。原因就是,我在demo这个类里面,重写了hashCode和equals方法,使得hashCode返回的哈希值是key的值(当然,每当我们重写一个类的equals方法的时候,最好也去重写它的hashCode方法)
18790965081080497174true
通过这一次研究,我们可以了解到hashset底层的实现原理是通过hashmap来进行编写的,以及hashset里面对于是否包含某一个元素的判断是通过hashmap里面对于key值的内容和key值的hashCode来进行判断的。
- Java集合框架(1)hashset
- Java 集合框架-HashSet
- java 集合框架-HashSet
- Java框架集合-Set(HashSet)
- java集合框架之HashSet
- java集合框架系列---HashSet
- Java基础--集合框架(HashSet、TreeSet、泛型)
- Java集合框架:Set(HashSet,LinkedHashSet,TreeSet)
- Java集合框架:Set(HashSet,LinkedHashSet,TreeSet)
- Java集合框架初步(hashset treeset list hashmap)
- 集合框架 HashSet集合
- 集合框架--HashSet集合
- Java集合框架-2.【Set】【HashSet】【TreeSet】
- java--集合框架的Hashset和Treeset
- java集合框架之HashSet类
- Java集合框架-LinkedList和HashSet
- Java集合框架-Hashset和HashMap
- Java基础之集合框架--HashSet
- Html form 表单提交前验证
- linux实战~zookeeper集群与solr集群
- java jdbc 查询与更新实现
- ZigBee缩略语和简称
- ssm框架整合的一些问题集合
- Java集合框架(1)hashset
- 那些年——5 杜拉拉升职记
- 使用hibernate生成表结构
- 【脚本语言系列】关于Python网页服务Apache,你需要知道的事
- 会计科目借贷方向记忆方法
- CSDN博客积分规则
- miui系统神隐模式导致app后台服务无法连接网络
- js之构造器模式(Constructor)
- shell脚本获取进程ID并杀死