下面的代码记录了hashmap的使用,包括增,删,改,查,需要注意如下几点:
1)在遍历的过程中,不能执行add操作,否则会抛出并发修改异常,
2)在遍历的过程中,remove操作必须借助iterator才可以,否则也会抛出并发修改的异常。
3)以对象作为key时,需要重写对象的equal和hashCode方法,
4)hashmap不是线程安全的,
5)iterator是官方推荐的标准遍历hashmap的方法,建议hashmap的遍历都基于iterator。
package com.basic.util;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
public class BasicMap {
public static void main(String argv[]) {
Person p1 = new Person(1, "liping", 1.0);
Person p2 = new Person(2, "liping", 1.0);
Person p3 = new Person(3, "liping", 1.0);
Map<Person, Integer> t = new HashMap<Person, Integer>();
// 存储
t.put(p1, 1);
t.put(p2, 2);
t.put(p3, 3);
// 删除
t.remove(p1);
// 更新
t.put(p1, 1);
t.put(p1, 11);
// 遍历
Iterator<Entry<Person, Integer>> itr = t.entrySet().iterator();
while (itr.hasNext()) {
Entry<Person, Integer> entry = itr.next();
System.out.println(entry.getKey().toString() + " " + entry.getValue());
}
Iterator<Person> itrK = t.keySet().iterator();
while (itrK.hasNext()) {
Person p = itrK.next();
System.out.println(p.toString() + " " + t.get(p));
}
Iterator<Integer> itrV = t.values().iterator();
while(itrV.hasNext()) {
Integer i = itrV.next();
System.out.println(i);
}
for (Entry<Person, Integer> entry : t.entrySet()) {
System.out.println(entry.getKey().toString() + " " + entry.getValue());
}
for (Person p : t.keySet()) {
System.out.println(p.toString() + " " + t.get(p));
}
for (Integer i : t.values()) {
System.out.println(i);
}
// 修改
Iterator<Entry<Person, Integer>> itrD = t.entrySet().iterator();
while (itrD.hasNext()) {
Entry<Person, Integer> entry = itrD.next();
if (entry.getValue() == 1) {
itrD.remove();
}
if (entry.getKey().equals(p2)) {
itrD.remove();
}
}
Iterator<Person> itrKD = t.keySet().iterator();
while (itrKD.hasNext()) {
Person p = itrKD.next();
if (p.equals(p1)) {
itrKD.remove();
}
}
Iterator<Integer> itrVD = t.values().iterator();
while(itrVD.hasNext()) {
Integer i = itrVD.next();
if (i == 1) {
itrVD.remove();
}
}
}
}
class Person {
private int age;
private String name;
private double money;
public Person(int age, String name, double money) {
this.age = age;
this.name = name;
this.money = money;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Person)) {
return false;
}
Person p = (Person)obj;
if (p.age != this.age)
return false;
if (!p.name.equals(this.name))
return false;
if (p.money != this.money)
return false;
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = result*prime + this.age;
result = result*prime + this.name.hashCode();
result = result*prime + (int)Double.doubleToLongBits(this.money);
return result;
}
@Override
public String toString() {
String str = this.name + " " + this.age + " " + this.money;
return str;
}
}
<span style="white-space:pre"> </span>public static void threadTest() {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 1; i <= 25; i++) {
firstHashMap.put(String.valueOf(i), String.valueOf(i));
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 26; i <= 50; i++) {
firstHashMap.put(String.valueOf(i), String.valueOf(i));
}
}
});
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 51; i <= 75; i++) {
firstHashMap.put(String.valueOf(i), String.valueOf(i));
}
}
});
Thread t4 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 76; i <= 100; i++) {
firstHashMap.put(String.valueOf(i), String.valueOf(i));
}
}
});
t1.start();
t2.start();
t3.start();
t4.start();
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println(firstHashMap.size());
Iterator<Entry<String, String>> iter = firstHashMap.entrySet().iterator();
while (iter.hasNext()) {
Entry<String, String> e = iter.next();
System.out.println(e.getKey() + " " + e.getValue());
}
}
<span style="font-family: Arial, Helvetica, sans-serif;">上面的threadTest函数的执行结果,最后map的大小不是100,说明出现了线程间覆盖的现象,是非线程安全的。</span>