HashMap学习小结
来源:互联网 发布:农历转换公历js 编辑:程序博客网 时间:2024/06/06 01:04
一、HashMap和TreeMap
在数组中,通过数组下标来对其内容索引;在Map中我们通过对象来对对象进行索引,用来索引的对象叫做key,其对应的对象叫做value。HashMap实现Map接口,提供所有映射操作的实现,并且允许null的键和值。HashMap中插入和查询key/value的开销是一个固定常量。HashMap不保证映射后的其内容的顺序在一定的时间内不会变化,也就是说,HashMap中元素的排列顺序是无序的(TreeMap是有序的)如例1:
例1:
import java.util.*;
class HashMaps
{
public static void main(String[] args)
{
HashMap map = new HashMap();
map.put("1", "111");
map.put("4", "444");
map.put("2", "222");
map.put("5", "555");
Iterator it = map.keySet().iterator();
while (it.hasNext())
{
Object mapKey = it.next();
System.out.println("map.get(key) is : " + map.get(mapKey));
}
TreeMap tree = new TreeMap();
tree.put("1", "111");
tree.put("4", "444");
tree.put("2", "222");
tree.put("5", "555");
Iterator it_2 = tree.keySet().iterator();
while(it_2.hasNext())
{
Object treeKey = it_2.next();
System.out.println("tree.get(key) is : " + tree.get(treeKey));
}
}
}
class HashMaps
{
public static void main(String[] args)
{
HashMap map = new HashMap();
map.put("1", "111");
map.put("4", "444");
map.put("2", "222");
map.put("5", "555");
Iterator it = map.keySet().iterator();
while (it.hasNext())
{
Object mapKey = it.next();
System.out.println("map.get(key) is : " + map.get(mapKey));
}
TreeMap tree = new TreeMap();
tree.put("1", "111");
tree.put("4", "444");
tree.put("2", "222");
tree.put("5", "555");
Iterator it_2 = tree.keySet().iterator();
while(it_2.hasNext())
{
Object treeKey = it_2.next();
System.out.println("tree.get(key) is : " + tree.get(treeKey));
}
}
}
map.get(key) is : 222
map.get(key) is : 111
map.get(key) is : 555
map.get(key) is : 444
tree.get(key) is : 111
tree.get(key) is : 222
tree.get(key) is : 444
tree.get(key) is : 555
因为HashMap通过hashCode对进行查找,所以HashMap中元素的排列顺序是不固定的,而TreeMap在查看key/value的时候,元素会被排序,其次序由Comparable或Comparator决定,因此查询得到的结果是有序地。如果你需要得到一个有序的结果你就应该使用TreeMap。
二、HashMap的使用
HashMap通过get()/put()方法来查询和插入,还有一个很有用的方法ContainsKey()来check对象是否存在于HashMap中。如例2:
例2:
import java.util.*;
public class HashMaps
{
public static void main(String[] args)
{
HashMap aMap = new HashMap();
Random ran = new Random();
for (int i = 0; i<100; i++)
{
Integer iVal = new Integer(ran.nextInt(10));
if (aMap.containsKey(iVal))
{
((CCount)aMap.get(iVal)).count++;
}
else
{
aMap.put(iVal, new CCount());
}
}
System.out.println(aMap);
}
}
class CCount
{
int count = 1;
public String toString()
{
return Integer.toString(count);
}
}
public class HashMaps
{
public static void main(String[] args)
{
HashMap aMap = new HashMap();
Random ran = new Random();
for (int i = 0; i<100; i++)
{
Integer iVal = new Integer(ran.nextInt(10));
if (aMap.containsKey(iVal))
{
((CCount)aMap.get(iVal)).count++;
}
else
{
aMap.put(iVal, new CCount());
}
}
System.out.println(aMap);
}
}
class CCount
{
int count = 1;
public String toString()
{
return Integer.toString(count);
}
}
HashMap是基于HashCode的,在所有对象的超类Object中有一个HashCode()方法。当使用标准库中的类Integer作为HashMap的key时,程序能够正常运行,但是如果使用自定义的类作为HashMap的key时,可能会出现错误。这是因为HashMap通过key查找value时,实际上是计算key对象地址的散列码来确定value的。默认情况下,我们使用超类Object的方法HashCode()来生成散列码。这样,假如我们用同样的初始化参数构造同样内容的对象,由于他们的地址不同,生成的散列码也不同。如下例所示:
例3:
import java.util.*;
public class HashMaps
{
public static void main(String[] args)
{
HashMap aMap = new HashMap();
for (int i = 0; i<10; i++)
aMap.put(new Element(i), new Figureout());
System.out.println("aMap: get result:");
Element test = new Element(5);
if (aMap.containsKey(test))
System.out.println((Figureout)aMap.get(test));
else
System.out.println("Not found");
}
}
class Element
{
int num;
public Element(int n)
{
num = n;
}
}
class Figureout
{
Random r = new Random();
boolean possible = r.nextDouble() > 0.5;
public String toString()
{
if (possible)
return "OK";
else
return "Impossible";
}
}
public class HashMaps
{
public static void main(String[] args)
{
HashMap aMap = new HashMap();
for (int i = 0; i<10; i++)
aMap.put(new Element(i), new Figureout());
System.out.println("aMap: get result:");
Element test = new Element(5);
if (aMap.containsKey(test))
System.out.println((Figureout)aMap.get(test));
else
System.out.println("Not found");
}
}
class Element
{
int num;
public Element(int n)
{
num = n;
}
}
class Figureout
{
Random r = new Random();
boolean possible = r.nextDouble() > 0.5;
public String toString()
{
if (possible)
return "OK";
else
return "Impossible";
}
}
例3中,先是在for循环中通过new Element(i)生成了一个HashMap,之后,我们希望查找一个test元素,这个test元素是通过new Element(5)生成的。test元素和HashMap中的元素是不同的对象,因此,它们的地址也不同,使用默认的Object超类提供的HashCode方法无法查找。所以,例3中程序执行结果始终是“Not found”。
因此,对于用户自定义的类作key的情况,我们需要覆盖HashCode方法。同时,还需要覆盖equals方法来判断当前的key是否与HashMap中的元素的key相同。修改后的Element类如下:
class Element
{
int num;
public Element(int n)
{
num = n;
}
public int hashCode()
{
return num;
}
public boolean equals(Object o)
{
return (o instanceof Element) && (num==((Element)o).num);
}
}
{
int num;
public Element(int n)
{
num = n;
}
public int hashCode()
{
return num;
}
public boolean equals(Object o)
{
return (o instanceof Element) && (num==((Element)o).num);
}
}
这里Element覆盖了Object中的hashCode()和equals()方法。覆盖hashCode()使其以number的值作为 hashCode返回,这样对于相同内容的对象来说它们的hashCode也就相同了。
三、小结
1,如果要用自己的类作为HashMap的key,必须同时覆盖hashCode和equals方法。
2,重写hashCode方法的关键:
(1)对同一个对象调用hashCode()都应该生成同样的值。
(2)hashCode()方法不要依赖于对象中易变的数据,当数据发生变化时,hashCode()就会生成一个不同的散列码,即产生了一个不同的label。
(3)hashCode()不应依赖于具有唯一性的对象信息,例如对象地址。
(4)散列码应该更关心速度,而不是唯一性,因为散列码不必是唯一的。
(5)好的hashCode()应该产生分步均匀的散列码。
3,正确的equals()方法满足五个条件:
(1)自反性。对于任意的x,x.equals(x)一定返回true。
(2)对称性。对于任意的x和y,如果y.equals(x)返回true,则x.equals(y)也返回true。
(3)传递性。对于任意的x、y、z,如果有x.equals(y)返回true,y.equals(z)返回true,则x.equals(z)一定返回true。
(4)一致性。对于任意的x和y,如果对象中用于等价比较的信息没有改变,那么无论调用x.equals(y)多少次,返回的结果应该保持一致,要么一直是true,要么一直是false。
(5)对任何不是null的x,x.equals(null)一定返回false。
- HashMap学习小结
- HASHMAP小结
- HashMap小结
- HashMap 使用小结
- HashMap 使用小结
- HashMap 使用小结
- HashMap 使用小结
- HashMap 使用小结
- HashMap 使用小结
- HashMap实现原理小结
- hashmap 理解小结
- HashMap使用小结
- Java HashMap源码小结
- hashtable和hashmap小结
- HashMap学习
- HashMap学习
- 学习HashMap
- HashMap学习
- using namespace std(部分问题)
- 遭遇auto.exe,winforms.dll,zinforms.dll,LYLoader.exe,LYLoadbr.exe等/1
- FTP协议的分析和扩展
- 首日安装debian的小问题
- JAVAMAIL核心类介绍
- HashMap学习小结
- CString,string,char*的综合比较
- post与get区别总结
- 原来MFC程序读取写放注册表就这么简单~
- 如何建立强有力的人脉关系?
- 我的Symbian的开发历程(一)
- vb.net读取dbf、Excel、Access数据文件
- 设备描述表(DC)
- 处理在DataGrid中的DropDownList的事件