最近一直在学习《算法》(第4版),当学习到了红黑树时,联想到了hashMap在1.8之后使用了红黑树,在弄懂了hashMap之后,思考了一下,Map有没有其他的实现方式?
打开java.util包,感觉有点乱,包里面有List有set,一个个找担心无法找全。
为了找到学习的重点,我想尝试扫描一下java.util包下有哪些Map的实现类。
第一步:工具方法-遍历获得某个包下的所有类文件的文件名
/**
* 工具方法
* 获得某个jar包中的所有类
*
* @param packagePath e.g java.util
* @param jarPath e.g C:/Program Files/java/jdk1.8.0_101/jre/lib/rt.jar
* @return
*/
static Set<String> getClassNameByJar(String packagePath, String jarPath) {
String packagePaths = packagePath.replace(".", "/").intern();
Set<String> myClassName = new HashSet<String>();
try {
JarFile jarFile = new JarFile(jarPath);
Enumeration<JarEntry> entrys = jarFile.entries();
while (entrys.hasMoreElements()) {
JarEntry jarEntry = entrys.nextElement();
String entryName = jarEntry.getName();
if (entryName.endsWith(".class")) {
if (entryName.startsWith(packagePaths)) {
entryName = entryName.replace("/", ".").substring(0, entryName.lastIndexOf("."));
myClassName.add(entryName);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return myClassName;
}
第二步:工具方法-根据文件名,得到所有实现了Map接口的Class
static Class reflect(String className) {
try {
Class clazz = Class.forName(className);
if (Map.class.isAssignableFrom(clazz)) {
return clazz;
}
} catch (Exception e) {
}
return null;
}
第三步:遍历打印所有结果
int count=0;
public BlobClassForEach() {
Set<String> classNames = getClassNameByJar("java.util", "C:/Program Files/java/jdk1.8.0_101/jre/lib/rt.jar");
Set<Class> set = new HashSet();
classNames.forEach(e -> {
Class clz = reflect(e);
if (clz != null) {
if (clz.isInterface()) {
System.out.print("Interface:");
} else if (Modifier.isAbstract(clz.getModifiers())) {
System.out.print("Abstract:");
} else {
System.out.print("Class:");
}
System.out.println("\t" + clz.getName());
count++;
}
});
System.out.println("count="+count);
}
通过以上方法,我们得到了所有的Map的实现类,将遍历的类进一步处理一下,去除内部类、接口和抽象类:
int count=0;
public BlobClassForEach() {
Set<String> classNames = getClassNameByJar("java.util", "C:/Program Files/java/jdk1.8.0_101/jre/lib/rt.jar");
Set<Class> set = new HashSet();
classNames.forEach(e -> {
if(!e.contains("$")){
Class clz = reflect(e);
if (clz != null) {
if (clz.isInterface()) {
// System.out.print("Interface:");
} else if (Modifier.isAbstract(clz.getModifiers())) {
//System.out.print("Abstract:");
} else {
System.out.print("Class:");
System.out.println("\t" + clz.getName());
count++;
}
}
}
});
System.out.println("count="+count);
}
结果:
java.util.LinkedHashMap |
java.util.TreeMap |
java.util.EnumMap |
java.util.Properties |
java.util.IdentityHashMap |
java.util.HashMap |
java.util.jar.Attributes |
java.util.concurrent.ConcurrentHashMap |
java.util.WeakHashMap |
java.util.Hashtable |
java.util.concurrent.ConcurrentSkipListMap |
上面11个javaMap的实现类,是java.util中最为重要的Map,根据以上类,整理了一下类图
(注:上述11个类为蓝色,父类和接口为白色)
附:map的实现类
使用场景 | 数据结构 | 线程安全 | |
java.util.HashMap | 比较快的增删改查 | 数组、链表、红黑树 | |
java.util.LinkedHashMap | 顺序地去存储key-value时 | 数组、双向链表、红黑树 | |
java.util.TreeMap | 能够自定义比较大小 | 红黑树 | |
java.util.EnumMap | 使用枚举替代hash值 | 数组 | |
java.util.IdentityHashMap | 一键多值记录,序列化或者深度复制 | 数组 | |
java.util.jar.Attributes | JAR 文件条目 | HashMap代理类 | |
java.util.concurrent.ConcurrentHashMap | 用于并发时,较快的增删改查 | 数组、链表 | 是 |
java.util.WeakHashMap | 弱引用的键值对,常用语缓存 | 基于hashtable实现 | 是 |
java.util.concurrent.ConcurrentSkipListMap | 有序键值对,建议在线程非常多时使用 | 数组、双向链表 | 是 |
java.util.Hashtable | 基本上被ConcurrentHashMap替代 | 数组、链表 | 是 |
java.util.Properties | 加载程序需要的配置信息 | 数组、链表 | 是 |