Java硬编码交换机与hashmap
某些消息类能够基于标记号返回标记名Java硬编码交换机与hashmap,java,performance,hashmap,Java,Performance,Hashmap,某些消息类能够基于标记号返回标记名 因为这个类被实例化了很多次,所以我有点不愿意为每个实例创建一个HashMap: public class Message { private HashMap<Integer,String> tagMap; public Message() { this.tagMap = new HashMap<Integer,String>(); this.tagMap.put( 1, "tag1Name"); thi
因为这个类被实例化了很多次,所以我有点不愿意为每个实例创建一个HashMap:
public class Message {
private HashMap<Integer,String> tagMap;
public Message() {
this.tagMap = new HashMap<Integer,String>();
this.tagMap.put( 1, "tag1Name");
this.tagMap.put( 2, "tag2Name");
this.tagMap.put( 3, "tag3Name");
}
public String getTagName( int tagNumber) {
return this.tagMap.get( tagNumber);
}
}
当您将所有内容(内存、性能、GC等)混合在一起时,有什么理由坚持使用HashMap吗?取决于您需要什么。例如,如果您曾经需要使用
Map
获取所有要显示的标记名,那么这样做是值得的。此外,如果用树形图替换,则可以对它们进行排序。
如果您没有这样的需求,那么使用Map
将是一种开销,并且您的方法或Enum
将更加高效(但与您选择的5-10-20case
options相比,您的可读性会更低)在静态块中初始化Map
由于您将创建许多消息对象,所以您应该编写如下代码
public class Message {
private static HashMap tagMap;
static {
tagMap = new HashMap();
tagMap.put( 1, "tag1Name");
tagMap.put( 2, "tag2Name");
tagMap.put( 3, "tag3Name");
}
public Message() {
}
public String getTagName( int tagNumber) {
return tagMap.get( tagNumber);
}
}
为什么不让getTaName方法成为静态的,并从属性文件中延迟加载它呢
public static String getTagName(int tagNumber) {
if tagsByID == null) {
// load tags from properties
}
return tagsByID.get(tagNumber);
}
易于测试和配置,无需重新编译。如果所有标记值在间隔[1..n]
中是连续的,则可以使用数组或数组列表
直接访问这些值
public class Message {
private ArrayList<String> tags;
public Message() {
this.tags = = new ArrayList<String>();
this.tags.add("Unknown");
this.tags.add("tag1Name");
this.tags.add("tag2Name");
this.tags.add("tag3Name");
}
public String getTagName(int tagNumber) {
return this.tags.get(tagNumber);
}
}
公共类消息{
私有ArrayList标签;
公共信息(){
this.tags==新的ArrayList();
此.tags.add(“未知”);
本.标记.添加(“标记名称”);
此.tags.add(“tag2Name”);
此.tags.add(“tag3Name”);
}
公共字符串getTagName(int标记号){
返回此.tags.get(tagNumber);
}
}
用数组替换
public class Message {
private static final String[] tags = {
"N/A",
"tag1Name",
"tag2Name",
"tag3Name",
null,
null,
"tag6Name",
};
public Message() {
}
public String getTagName(int tagNumber) {
if (tagNumber < 0 || tagNumber > tags.length) {
throw new IllegalArgumentException();
return tags[tagNumber];
}
}
公共类消息{
私有静态最终字符串[]标记={
“不适用”,
“tag1Name”,
“tag2Name”,
“tag3Name”,
无效的
无效的
“tag6Name”,
};
公共信息(){
}
公共字符串getTagName(int标记号){
if(标记编号<0 | |标记编号>标记长度){
抛出新的IllegalArgumentException();
返回标签[tagNumber];
}
}
Map可用作命令模式,其中键表示条件,值表示要执行的命令唯一的缺点是在使用之前创建对象,因此如果您有大量此类条件,则可以选择Map-else开关如果您的条件很少,则开关始终是优雅的方法。这不是吗enum
最理想的情况是什么?如果所有消息的列表都相同,您也可以将映射设置为静态。此外,您(通过分析)也这样做了吗确定类的实例化确实是一个问题吗?枚举不合适,因为某些标记编号可能未知如果映射是静态的,那么后续调用put()会发生什么情况?我不知道调用put()的方法在静态块中。使用映射不能比使用开关快,这没有任何意义。@Byter是否有任何证据证明映射(以及映射的什么实现)比开关快吗?你真的测试过吗?@joergl我不喜欢使用它们。这里的大量响应表明,通常都有替代方法。另外,在进行单元测试时,你通常必须编写额外的代码来处理它们。这只是我的意见。你甚至可能想添加tagMap=Collections.unmodifiableMap(标记图)
当然,只有在静态块之后,地图在运行时不会更改时才可以。不幸的是,它不是连续的list@AknownImous太糟糕了。但我还是会保留我的答案。@AknownImous你知道标签是如何编号的吗?也许你可以在数组中允许一些间隙,而不会占用太多内存。属性文件因为列表是静态的,我宁愿嵌入映射。
public class Message {
private static final String[] tags = {
"N/A",
"tag1Name",
"tag2Name",
"tag3Name",
null,
null,
"tag6Name",
};
public Message() {
}
public String getTagName(int tagNumber) {
if (tagNumber < 0 || tagNumber > tags.length) {
throw new IllegalArgumentException();
return tags[tagNumber];
}
}