Writer:BYSocket(泥沙砖瓦浆木匠)
微博:BYSocket
豆瓣: BYSocket
Java 容器的文章这次应该是最后一篇了: Java 容器 系列。 今天泥瓦匠聊下 Maps。
Map,又称映射表,是将键映射到值的对象。有四种实现Map接口并且经常使用的Map集合为:HashMap,TreeMap,Hashtable 和 LinkedHashMap.
泥瓦匠记忆宫殿:
1、一个映射 不包含重复的键 。
2、每个键 最多 只能映射到一个值。
HashMap是基于哈希表的Map接口的实现。其对键进行散列,散列函数只能作用于键。下面模拟下,公司员工和找员工的例子:
import java.util.HashMap;
import java.util.Map;
class Employee
{}
public class HaspMap01
{
public static void main(String[] args)
{
Map<
String
, Employee> employees = new HashMap<
String
, Employee>();
employees.put("1206010035", new Employee());
System.out.println(employees);
String number = "1206010035";
System.out.println(employees.get(number));
}
}
Run一下,大家可以见到结果:put方法,可以将键值映射添加进表。get方法则返回指定键所映射的值。从他们 hashCode 可以看出是同一个对象。
HaspMap的键必须唯一,同样其 同一个键不能存放两个值 ,如果对同一个键两次调用put方法,第二个值会取代第一个值。同样是允许使用 null 值和 null 键。下面泥瓦匠用一个简单的例子解释下:
package javaBasic.collection.map;
import java.util.HashMap;
import java.util.Map;
public class HaspMap02
{
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void main(String[] args)
{
Map map = new HashMap<
String
, String>();
map.put(null, "null01");
map.put(null, "null02");
System.out.println(map);
System.out.println(map.get(null));
}
}
结果如下:
{null=null02}
null02
由此可见,第一个值被第二个值所替换了。
下面有三点是HashMap重要之处:
1、HashMap的构造函数
HaspMap构造函数涉及两个参数:初始容量和加载因子。初试容量是哈希表创建时的其中桶的含量。加载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度。这两个参数都是影响HashMap的性能。默认构造一个具有默认初始容量 (16) 和默认加载因子 (0.75)。默认加载因子 (.75) 在时间和空间成本上是一种折衷的考虑。
2、和上次总结的Set都差不多,这个HashMap线程是不安全不同步的。如果想防止意外发生,则设置成同步即可:
Map m = Collections.synchronizedMap(new HashMap(...));
3、不同步的话,意味着存在快速失败导致的并发修改异常。
下面看一个复杂例子:
package javaBasic.collection.map;
import java.util.HashMap;
import java.util.Map.Entry;
class A
{
public boolean equals(Object obj)
{
return true;
}
}
class B
{
public int hashCode()
{
return 1;
}
}
class C
{
public int hashCode()
{
return 2;
}
public boolean equals(Object obj)
{
return true;
}
}
public class HashMap03
{
public static void main(String[] args)
{
HashMap<
A
, Integer> hashMapA = new HashMap<
A
, Integer>();
hashMapA.put(new A(), 10);
hashMapA.put(new A(), 5);
System.out.println("HashMapA Elements:");
System.out.print("/t" + hashMapA + "/n");
// loop HashMapA
for(Entry<
A
, Integer> entryA : hashMapA.entrySet())
{
System.out.println(entryA.getKey().toString()+"-"+entryA.getValue());
}
HashMap<
B
, Integer> hashMapB = new HashMap<
B
, Integer>();
hashMapB.put(new B(), 10);
hashMapB.put(new B(), 5);
System.out.println("HashMapB Elements:");
System.out.print("/t" + hashMapB + "/n");
// loop HashMapB
for(Entry<
B
, Integer> entryB : hashMapB.entrySet())
{
System.out.println(entryB.getKey().toString()+"-"+entryB.getValue());
}
HashMap<
C
, Integer> hashMapC = new HashMap<
C
, Integer>();
hashMapC.put(new C(), 10);
hashMapC.put(new C(), 5);
System.out.println("HashMapC Elements:");
System.out.print("/t" + hashMapC + "/n");
// loop HashMap
for(Entry<
C
, Integer> entryC : hashMapC.entrySet())
{
System.out.println(entryC.getKey().toString()+"-"+entryC.getValue());
}
}
}
运行一下,可以看到以下结果:
由此可见,其中和 Java 容器 & 泛型:三、HashSet,TreeSet 和 LinkedHashSet比较 中涉及的知识点一致:
集合判断两个元素相等不单单是 equals 方法,并且必须 hashCode ()方法返回值也要相等。
TreeMap使用树结构实现(红黑树),集合中的元素进行排序,但是添加、删除和包含的算法复杂度为O(log(n))。其实Map特性基本都是一致的,比如看下面的简单例子:
public class TreeMap01
{
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void main(String[] args)
{
Map map = new TreeMap();
map.put("1", "1");
map.put("4", "4");
map.put("2", "2");
map.put("2", "3");
System.out.println(map);
}
}
结果如下:
{1=1, 2=3, 4=4}
从中我们可以看出
1、TreeMap实现了SortedMap,顾名思义,其表示为有排序的集合。
2、同样其同一个键不能存放两个值,如果对同一个键两次调用put方法,第二个值会取代第一个值。
Writer:BYSocket(泥沙砖瓦浆木匠)
微博:BYSocket
豆瓣: BYSocket