(50) 剖析EnumMap / 计算机程序的思维逻辑

 

本节介绍EnumMap的用法和实现原理,为什么要针对枚举类型单独实现一个Map?它的用法和其他Map有什么不同?内部是如何实现的?......



查看历史文章,请点击上方链接关注公众号。

上节我们提到,如果需要一个Map的实现类,并且键的类型为枚举类型,可以使用HashMap,但应该使用一个专门的实现类EnumMap。

为什么要有一个专门的类呢?我们之前介绍过枚举的本质,主要是因为枚举类型有两个特征,一是它可能的值是有限的且预先定义的,二是枚举值都有一个顺序,这两个特征使得可以更为高效的实现Map接口。

我们先来看EnumMap的用法,然后看它到底是怎么实现的。

用法


举个简单的例子,比如,有一批关于衣服的记录,我们希望按尺寸统计衣服的数量。

定义一个简单的枚举类,Size,表示衣服的尺寸:

public enum Size {
SMALL, MEDIUM, LARGE
}

定义一个简单类,Clothes,表示衣服:

class Clothes {
String id;
Size size;

public Clothes(String id, Size size) {
this.id = id;
this.size = size;
}

public String getId() {
return id;
}

public Size getSize() {
return size;
}
}

有一个表示衣服记录的列表List,我们希望按尺寸统计数量,统计方法可以为:

public static Map countBySize(List clothes){
Map map = new EnumMap(Size.class);
for(Clothes c : clothes){
Size size = c.getSize();
Integer count = map.get(size);
if(count!=null){
map.put(size, count+1);
}else{
map.put(size, 1);
}
}
return map;
}

大部分代码都很简单,需要注意的是EnumMap的构造方法,如下所示:

Map map = new EnumMap(Size.class);

与HashMap不同,它需要传递一个类型信息,我们在37节简单介绍过运行时类型信息,Size.class表示枚举类Size的运行时类型信息,Size.class也是一个对象,它的类型是Class。

为什么需要这个参数呢?没有这个,EnumMap就不知道具体的枚举类是什么,也无法初始化内部的数据结构。

使用以上的统计方法也是很简单的,比如:

List clothes = Arrays.asList(new Clothes[]{
new Clothes("C001",Size.SMALL),
new Clothes("C002", Size.LARGE),
new Clothes("C003", Size.LARGE),
new Clothes("C004", Size.MEDIUM),
new Clothes("C005", Size.SMALL),
new Clothes("C006", Size.SMALL),
});
System.out.println(countBySize(clothes));

输出为:

{SMALL=3, MEDIUM=1, LARGE=2}

需要说明的是,EnumMap是保证顺序的,输出是按照键在枚举中的顺序的。

除了以上介绍的构造方法,EnumMap还有两个构造方法,可以接受一个键值匹配的EnumMap或普通Map,如下所示:

public EnumMap(EnumMap m)

public EnumMap(Map m)

比如:

Map hashMap = new HashMap();
hashMap.put(Size.LARGE, 2);
hashMap.put(Size.SMALL, 1);
Map enumMap = new EnumMap(hashMap);

以上就是EnumMap的基本用法,与HashMap的主要不同,一是构造方法需要传递类型参数,二是保证顺序。

有人可能认为,对于枚举,使用Map是没有必要的,比如对于上面的统计例子,可以使用一个简单的数组:

public static int[] countBySize(List clothes){
int[] stat = new int[Size.values().length];
for(Clothes c : clothes){
Size size = c.getSize();
stat[size.ordinal()]++;
}
return stat;
}

这个方法可以这么使用:

[quote]List clothes = Arrays.asList(new Clothes[]{
new Clothes("C001",Size.SMALL),
new Clothes("C002", Size.LARGE),
new Clothes("C003", Size.LARGE),
new Clothes("C004", Size.MEDIUM),
new Clothes("C005", Size.SMALL),
new Clothes("C006", Size.SMALL),
});
int[] stat = countBySize(clothes);
for(int i=0; i


    关注 老马说编程


微信扫一扫关注公众号

0 个评论

要回复文章请先登录注册