Java 按值查找枚举的正确方法
我有几个Java枚举,如下所示(为了保密等而编辑)。 在每种情况下,我都有一个查找方法,我真的不满意;在下面的示例中,它是Java 按值查找枚举的正确方法,java,enums,Java,Enums,我有几个Java枚举,如下所示(为了保密等而编辑)。 在每种情况下,我都有一个查找方法,我真的不满意;在下面的示例中,它是findByChannelCode public enum PresentationChannel { ChannelA("A"), ChannelB("B"), ChannelC("C"), ChannelD("D"), ChannelE("E"); private String channelCode; Pres
findByChannelCode
public enum PresentationChannel {
ChannelA("A"),
ChannelB("B"),
ChannelC("C"),
ChannelD("D"),
ChannelE("E");
private String channelCode;
PresentationChannel(String channelCode) {
this.channelCode = channelCode;
}
public String getChannelCode() {
return this.channelCode;
}
public PresentationChannel findByChannelCode(String channelCode) {
if (channelCode != null) {
for (PresentationChannel presentationChannel : PresentationChannel.values()) {
if (channelCode.equals(presentationChannel.getChannelCode())) {
return presentationChannel;
}
}
}
return null;
}
}
问题是,当我可以只使用HashMap
时,我觉得做这些线性查找很愚蠢。所以我想到了下面的解决方案,但我希望它有点混乱,更重要的是,当肯定有其他人遇到这个问题时,我不想重新发明轮子。我想了解这个群体的一些智慧:什么是按值索引枚举的正确方法
我的解决方案:
ImmutableMap<String, PresentationChannel> enumMap = Maps.uniqueIndex(ImmutableList.copyOf(PresentationChannel.values()), new Function<PresentationChannel, String>() {
public String apply(PresentationChannel input) {
return input.getChannelCode();
}});
如果希望提供的channelCode始终有效,则可以尝试使用valueOf()方法获取正确的枚举实例。如果提供的值无效,则可以返回null或传播异常
try {
return PresentationChannel.valueOf(channelCode);
catch (IllegalArgumentException e) {
//do something.
}
你为什么不把你的成员命名为A、B、C、D、E并使用它们呢?我认为你在这里使用的是非JDK类,对吗 使用JDK API的类似解决方案:
private static final Map<String, PresentationChannel> channels = new HashMap<String, PresentationChannel>();
static{
for (PresentationChannel channel : values()){
channels.put(channel.getChannelCode(), channel);
}
}
private static final Map channels=new HashMap();
静止的{
对于(PresentationChannel:values()){
channels.put(channel.getChannelCode(),channel);
}
}
对于少数确定的值,通过值数组()进行迭代。只需注意一点:像这样使用smth<代码>值()在每次调用时克隆数组
static final PresentationChannel[] values=values();
static PresentationChannel getByCode(String code){
if (code==null)
return null;
for(PresentationChannel channel: values) if (code.equals(channel.channelCode)) return channel;
return null;
}
如果你有更多的频道
private static final Map<String code, PresentationChannel> map = new HashMap<String code, PresentationChannel>();
static{//hashmap sucks a bit, esp if you have some collisions so you might need to initialize the hashmap depending on the values count and w/ some arbitrary load factor
for(PresentationChannel channel: values()) map.put(channel.channelCode, channel);
}
static PresentationChannel getByCode(String code){
return map.get(code);
}
次要警告:如果您将可识别的映射放在某个地方,并且许多项目/wepapp依赖它(并共享它)等等,则可能会泄漏类/类加载器。下面是实现不可修改映射的另一种方法:
protected static final Map<String, ChannelCode> EnumMap;
static {
Map<String, ChannelCode> tempMap = new HashMap<String, ChannelCode>();
tempMap.put("A", ChannelA);
tempMap.put("B", ChannelB);
tempMap.put("C", ChannelC);
tempMap.put("D", ChannelD);
tempMap.put("E", ChannelE);
EnumMap = Collections.unmodifiableMap(tempMap);
}
受保护的静态最终映射枚举映射;
静态{
Map tempMap=newhashmap();
tempMap.put(“A”,ChannelA);
tempMap.put(“B”,ChannelB);
tempMap.put(“C”,ChannelC);
tempMap.put(“D”,ChannelD);
tempMap.put(“E”,ChannelE);
EnumMap=Collections.unmodifiableMap(tempMap);
}
您可以使用EnumMap.get(somecodeathrough)
快速检索通道代码。如果表达式为null,则找不到您的SomeCodeAthrawe
我想了解这个群体的一些智慧:什么是按值索引枚举的正确方法
很可能根本不做
虽然哈希表提供O(1)
查找,但它们也有相当大的固定开销(用于哈希计算等),因此对于小集合,线性搜索可能会更快(如果“有效方式”是您对“正确方式”的定义)
如果你只是想用一种干燥的方法来做,我想番石榴的Iterables.find
是一种替代品:
return channelCode == null ? null : Iterables.find(Arrays.asList(values()),
new Predicate<PresentationChannel>() {
public boolean apply(PresentationChannel input) {
return input.getChannelCode().equals(channelCode);
}
}, null);
返回channelCode==null?null:Iterables.find(Arrays.asList(values()),
新谓词(){
公共布尔应用(PresentationChannel输入){
返回input.getChannelCode().equals(channelCode);
}
},空);
我一直在寻找类似的东西,并找到了一种简单、干净、直截了当的方法。在枚举内创建并初始化静态最终映射,并为查找添加一个静态方法,因此类似于:
public enum PresentationChannel {
ChannelA("A"),
ChannelB("B"),
ChannelC("C"),
ChannelD("D"),
ChannelE("E");
private String channelCode;
PresentationChannel(String channelCode) {
this.channelCode = channelCode;
}
public String getChannelCode() {
return this.channelCode;
}
private static final Map<String, PresentationChannel> lookup
= new HashMap<String, PresentationChannel>();
static {
for(PresentationChannel pc : EnumSet.allOf(PresentationChannel.class)) {
lookup.put(pc.getChannelCode(), pc);
}
}
public static PresentationChannel get(String channelCode) {
return lookup.get(channelCode);
}
}
公共枚举表示通道{
渠道A(“A”),
渠道B(“B”),
渠道C(“C”),
渠道D(“D”),
渠道E(“E”);
专用字符串信道码;
PresentationChannel(字符串通道代码){
this.channelCode=channelCode;
}
公共字符串getChannelCode(){
返回此.channelCode;
}
私有静态最终映射查找
=新HashMap();
静止的{
for(PresentationChannel pc:EnumSet.allOf(PresentationChannel.class)){
lookup.put(pc.getChannelCode(),pc);
}
}
公共静态表示通道获取(字符串通道代码){
返回lookup.get(channelCode);
}
}
你知道enumMap映射的是enum->Object,而不是相反?代码分析是否表明线性查找不充分?@bestsss,也许我的映射命名不好。它不是EnumMap,只是String->PresentationChannel(即value->instance)@trashgod的映射,在这里的示例中,为了清晰起见,只有几个实例。在实际的代码中,这个习惯用法的例子很多,而且查找也经常发生。。。我编辑答案是为了让您明白,基本上,您需要一个外部存储库和一个接口来实现。因为它们也可以像1,2,3,4那样,或者像ааааС1、ааааааааааааа2等等,即不是java标识符。我不希望名称与值紧密耦合。关于“我所。它不一定是最有效的。如果有不必要的开销,那就不好了。如果它容易出错,那也不好。我想我在想“Josh Bloch会做什么?”是的,这可能是“正确的方式”的一个很好的定义。@Ray,Joshua在java 1.4中炸掉了AbstractCollection.toArray()和新的ArrayList(Collection),从那时起,我就有了一些分歧。@gustafc我想提出一个更正/建议-EnumMap是一个非常有效的映射。不需要散列,因为它可以使用带有内部索引的数组作为枚举值。@确实如此,但它们仅在键为枚举时才起作用,这里不是这种情况。您可以使用PresentationChannel.values()
return channelCode == null ? null : Iterables.find(Arrays.asList(values()),
new Predicate<PresentationChannel>() {
public boolean apply(PresentationChannel input) {
return input.getChannelCode().equals(channelCode);
}
}, null);
public enum PresentationChannel {
ChannelA("A"),
ChannelB("B"),
ChannelC("C"),
ChannelD("D"),
ChannelE("E");
private String channelCode;
PresentationChannel(String channelCode) {
this.channelCode = channelCode;
}
public String getChannelCode() {
return this.channelCode;
}
private static final Map<String, PresentationChannel> lookup
= new HashMap<String, PresentationChannel>();
static {
for(PresentationChannel pc : EnumSet.allOf(PresentationChannel.class)) {
lookup.put(pc.getChannelCode(), pc);
}
}
public static PresentationChannel get(String channelCode) {
return lookup.get(channelCode);
}
}