HashMap and HashSet
2013-07-31 19:33
323 查看
HashMap和HashSet
对于HashSet来说,系统采用Hash算法决定集合元素的存储位置,这样可以保证快速存,取集合元素;对于HashMap来说,系统将value当成key的附属,系统根据Hash算法来决定key的存储位置,这样可以保证快速存,取集合key,而value总是紧随key存储。
虽然集合号称存储的是Java对象,但实际上并不会真正将Java对象放入Set集合中,而只是在Set集合中保留这些对象的引用而已。也就是说,Java集合实际上是多个引用变量所组成的集合,这些引用变量指向实际的Java对象。
import java.util.ArrayList;
import java.util.List;
class Apple{
doubleweight;
public Apple(double weight){
this.weight = weight;
}
}
publicclass ListTest {
publicstaticvoid main(String[] args){
Apple t1 = new Apple(2.2);
Apple t2 =new Apple(1.8);
List<Apple> list = new ArrayList<Apple>(4);
list.add(t1);
list.add(t2);
System.out.println(list.get(0)==t1);
System.out.println(list.get(1)==t2);
}
}
Output:
true
true
ArrayList底层是基于数组实现的,也就是说ArrayList底层封装的是数组,每次创建时传入的int参数就是它包装的数组的长度;
对于HashMap而言,它的存储方式要比ArrayList复杂一些,采用所谓的”Hash算法”来决定每个元素的存储位置。
当执行程序map.put(“yuwen”,80.0)时,系统将调用”yuwen”的hashcode()方法得到其hashcode值――每个Java对象都有hashcode()方法,都可通过该方法获得它的hashcode的值。得到这个值后,系统会根据该hashcode值来决定该元素的存储位置。
HashMap在底层将key-value当成一个整体进行处理,这个整体就是一个Entry对象。HashMap底层采用一个Entry[]数组来保存所有的key-value对,当需要存储一个Entry对象时,会根据Hash算法来决定其存储位置;当需要取出一个Entry时,也会根据Hash算法找到其存储位置,直接取出该Entry。由此可见,HashMap之所以能快速存,取它所包含的Entry,完全类似于生活中,不同的东西要放在不同的位置,需要时才能快速找到它。
当创建HashMap时,有一个默认的负载因子(load factor),其默认值为0.75.增大负载因子可以减少Hash表(就是那个Entry数组)所占用的内存空间,但会增加查询数据的时间开销,而查询是最频繁的操作(HashMap的get()与put()方法都要用到查询);减小负载因子会提高数据查询的功能,但会降低Hash表所占用的内存空间。
如果开始就知道HashMap会保存多个key-value对,可以在创建时就使用较大的初始化容器,如果Entry的数量一直不会超过极限容量(capacity*load
factor),HashMap就无需调用resize()方法重新分配table数组,从而保证较好的性能。当然,开始就将初始容量设置太高可能会浪费空间(系统需要创建一个长度为capacity的Entry数组),因此创建HashMap时初始化容量设置也需要小心对待。对于HashSet而言,它是基于HashMap实现的。HashSet底层采用HashMap来保存所有元素。
import java.util.HashSet;
import java.util.Set;
class Name{
private Stringfirst;
private Stringlast;
public Name(String first,String last){
this.first = first;
this.last = last;
}
publicboolean equals(Object o){
if(this == o){
returntrue;
}
if(o.getClass() == Name.class){
Name n = (Name)o;
return n.first.equals(first)
&& n.last.equals(last);
}
returnfalse;
}
}
publicclass HashSetTest {
publicstaticvoid main(String[] args){
Set<Name> s = new HashSet<Name>();
s.add(new Name("abc","123"));
System.out.println(s.contains(new Name("abc","123")));
}
}
Output:
False
输出false的原因是因为HashSet判断两个对象相等的标准除了要求通过equals()方法比较返回的true之外,还要求两个对象的hashCode()返回值相等,上面的程序没有重写hashCode()方法。
对于HashSet来说,系统采用Hash算法决定集合元素的存储位置,这样可以保证快速存,取集合元素;对于HashMap来说,系统将value当成key的附属,系统根据Hash算法来决定key的存储位置,这样可以保证快速存,取集合key,而value总是紧随key存储。
虽然集合号称存储的是Java对象,但实际上并不会真正将Java对象放入Set集合中,而只是在Set集合中保留这些对象的引用而已。也就是说,Java集合实际上是多个引用变量所组成的集合,这些引用变量指向实际的Java对象。
import java.util.ArrayList;
import java.util.List;
class Apple{
doubleweight;
public Apple(double weight){
this.weight = weight;
}
}
publicclass ListTest {
publicstaticvoid main(String[] args){
Apple t1 = new Apple(2.2);
Apple t2 =new Apple(1.8);
List<Apple> list = new ArrayList<Apple>(4);
list.add(t1);
list.add(t2);
System.out.println(list.get(0)==t1);
System.out.println(list.get(1)==t2);
}
}
Output:
true
true
ArrayList底层是基于数组实现的,也就是说ArrayList底层封装的是数组,每次创建时传入的int参数就是它包装的数组的长度;
对于HashMap而言,它的存储方式要比ArrayList复杂一些,采用所谓的”Hash算法”来决定每个元素的存储位置。
当执行程序map.put(“yuwen”,80.0)时,系统将调用”yuwen”的hashcode()方法得到其hashcode值――每个Java对象都有hashcode()方法,都可通过该方法获得它的hashcode的值。得到这个值后,系统会根据该hashcode值来决定该元素的存储位置。
HashMap在底层将key-value当成一个整体进行处理,这个整体就是一个Entry对象。HashMap底层采用一个Entry[]数组来保存所有的key-value对,当需要存储一个Entry对象时,会根据Hash算法来决定其存储位置;当需要取出一个Entry时,也会根据Hash算法找到其存储位置,直接取出该Entry。由此可见,HashMap之所以能快速存,取它所包含的Entry,完全类似于生活中,不同的东西要放在不同的位置,需要时才能快速找到它。
当创建HashMap时,有一个默认的负载因子(load factor),其默认值为0.75.增大负载因子可以减少Hash表(就是那个Entry数组)所占用的内存空间,但会增加查询数据的时间开销,而查询是最频繁的操作(HashMap的get()与put()方法都要用到查询);减小负载因子会提高数据查询的功能,但会降低Hash表所占用的内存空间。
如果开始就知道HashMap会保存多个key-value对,可以在创建时就使用较大的初始化容器,如果Entry的数量一直不会超过极限容量(capacity*load
factor),HashMap就无需调用resize()方法重新分配table数组,从而保证较好的性能。当然,开始就将初始容量设置太高可能会浪费空间(系统需要创建一个长度为capacity的Entry数组),因此创建HashMap时初始化容量设置也需要小心对待。对于HashSet而言,它是基于HashMap实现的。HashSet底层采用HashMap来保存所有元素。
import java.util.HashSet;
import java.util.Set;
class Name{
private Stringfirst;
private Stringlast;
public Name(String first,String last){
this.first = first;
this.last = last;
}
publicboolean equals(Object o){
if(this == o){
returntrue;
}
if(o.getClass() == Name.class){
Name n = (Name)o;
return n.first.equals(first)
&& n.last.equals(last);
}
returnfalse;
}
}
publicclass HashSetTest {
publicstaticvoid main(String[] args){
Set<Name> s = new HashSet<Name>();
s.add(new Name("abc","123"));
System.out.println(s.contains(new Name("abc","123")));
}
}
Output:
False
输出false的原因是因为HashSet判断两个对象相等的标准除了要求通过equals()方法比较返回的true之外,还要求两个对象的hashCode()返回值相等,上面的程序没有重写hashCode()方法。
相关文章推荐
- 【Data Structures】 12. Hashing, HashMap and HashSet in Java
- Java - Difference between HashMap and HashSet in Java
- HashMap, HashTable and HashSet
- Java HashMap and HashSet
- (Core-JAVA) HashMap, HashTable and HashSet
- LinkedHashMap and LinkedHashSet
- Difference between HashSet and HashMap in Java
- HashSet HashTable HashMap 区别
- stl vector、红黑树、set、multiset、map、multimap、迭代器失效、哈希表(hash_table)、hashset、hashmap、unordered_map、list
- HashTable vs HashMap vs HashSet
- JDK源码研究之-----------HashMap AND HashCode
- HashSet ArrayList HashMap遍历的两种形式
- 集合 List ArrayList LinkedList HashMap HashSet Iterator 迭代器
- 【JAVA基础】集合类源码分析_HashMap/HashSet
- Java HashSet和HashMap源码剖析
- hashset hashmap hashtable arraylist vector 区别
- 剖析HASHMAP/HASHSET
- Java集合框架初步(hashset treeset list hashmap)
- HashMap HashTable HashSet
- Java List/HashSet/HashMap的排序