Java 实现N个常量之间链接的最佳方法
我找不到更好的标题(如果找到更好的,请随意编辑),但用例如下。我有两个常量列表。其中一个包含我在应用程序中使用的常量,另一个包含通过CSV文件发送给我的不同常量(以及数据) 举一个粗略的例子:在CSV文件中,有一个名为“客户id”的字段。在我的应用程序中,我想使用一个名为“clientId”的字段。所以我基本上需要在这两个常量之间创建一个静态链接,这样我就可以根据需要轻松地从一个常量切换到另一个常量 我曾考虑过创建一个静态的Java 实现N个常量之间链接的最佳方法,java,hashmap,constants,Java,Hashmap,Constants,我找不到更好的标题(如果找到更好的,请随意编辑),但用例如下。我有两个常量列表。其中一个包含我在应用程序中使用的常量,另一个包含通过CSV文件发送给我的不同常量(以及数据) 举一个粗略的例子:在CSV文件中,有一个名为“客户id”的字段。在我的应用程序中,我想使用一个名为“clientId”的字段。所以我基本上需要在这两个常量之间创建一个静态链接,这样我就可以根据需要轻松地从一个常量切换到另一个常量 我曾考虑过创建一个静态的值映射(String,String),但我认为可能有更好的解决方案 谢谢
值映射(String,String)
,但我认为可能有更好的解决方案
谢谢
编辑:将标题改为“N”常量,而不是2,因为在这种情况下Hashmap似乎不再是一个选项。您可以使用双括号innitializer习惯用法来保持映射初始化接近映射声明,因此它不会那么“丑陋”,例如:
静态映射someMap=newhashmap(){{
放入(“一”、“二”);
放置(“三”、“四”);
}};
请注意,如果没有static
修饰符,每个匿名类(本例中创建了一个)都会持有对封闭对象的引用,如果您将此映射的引用提供给其他某个类,则会防止封闭类被垃圾回收
幸运的是,java update为我们带来了希望,在java 9中,将有非常方便的
Map.of()
来帮助我们更安全地完成此操作。将映射与应用程序代码分离的最佳方法是使用一个属性文件,在其中定义映射
例如,您可以在资源的根目录中有一个csv mapping.properties
,并使用以下代码加载它们:
final Properties properties = new Properties();
properties.load( this.getClass().getResourceAsStream( "/csv-mapping.properties" ) );
这就像一个映射,增加了代码与配置的分离。有许多方法可以用来轻松解决这些类型的问题。 一种方法是使用属性文件或包含键值对的文件 下面是属性的代码
import java.util.ResourceBundle;
public class ReadingPropertiesFile {
public static void main(String[] args) {
ResourceBundle messages;
messages = ResourceBundle.getBundle("msg");
System.out.println(messages.getString("ID"));
}
}
msg.properties文件包含以下值:
ID=ClientID。
产品标识=产品标识
程序的输出是ClientID
也可以从简单的文本文件中读取。或者你可以在使用地图时使用它。但是我建议您使用属性文件。一个好的选择是使用枚举创建多个常量到单个常识值之间的映射,例如:
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public enum MappingEnum {
CLIENT_ID("clientId", "id of the client", "clientId", "IdOfTheClient"),
CLIENT_NAME("clientName", "name of the client", "clientName");
private Set<String> aliases;
private String commonSenseName;
private MappingEnum(String commonSenseName, String... aliases) {
this.commonSenseName = commonSenseName;
this.aliases = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(aliases)));
}
public static MappingEnum fromAlias(String alias) {
for (MappingEnum mappingEnum : values()) {
if (mappingEnum.getAliases().contains(alias)) {
return mappingEnum;
}
}
throw new RuntimeException("No MappingEnum for mapping: " + alias);
}
public String getCommonSenseName() {
return commonSenseName;
}
}
那么,使用静态映射有什么错呢?主要是它需要填充一个static(){}方法,如果列表变得很长,那么这个方法实际上是非常难看的代码。但它可能是最好的解决方案,只是想在我选择它之前确定一下。此外,如果我的应用程序中需要第三层(如我需要创建并发送给第三方的文件),并且因此需要将3个常量链接在一起,则此解决方案将不起作用。映射似乎是最好的选择,但它不必是静态的。将它封装到类中。Guava的
ImmutableMap
很棒,并且有一个很好的语法来构造它:ImmutableMap.of(“客户端id”、“客户端id”、“客户端id”…)
。然后你也可以确定它不会被意外修改。等等什么?何时添加此功能?我从来不知道这存在@清洁工看一看这里:嗯,这实际上是相当甜蜜的。我也不知道这是存在的,就拿我的科学投票来说吧。:)我开始使用这个自动取款机了,如果一段时间内没有其他/更好的想法出现,我会接受它作为答案。谢谢!这个成语确实有缺点。例如,它创建了一个额外的.class文件。您分配给它的变量不是一个实际的HashMap,而是它的一个子类。你可以用谷歌搜索这个习惯用法的其他缺点。这不一定是个坏习惯用语;只是指出一些需要注意的事情。
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public enum MappingEnum {
CLIENT_ID("clientId", "id of the client", "clientId", "IdOfTheClient"),
CLIENT_NAME("clientName", "name of the client", "clientName");
private Set<String> aliases;
private String commonSenseName;
private MappingEnum(String commonSenseName, String... aliases) {
this.commonSenseName = commonSenseName;
this.aliases = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(aliases)));
}
public static MappingEnum fromAlias(String alias) {
for (MappingEnum mappingEnum : values()) {
if (mappingEnum.getAliases().contains(alias)) {
return mappingEnum;
}
}
throw new RuntimeException("No MappingEnum for mapping: " + alias);
}
public String getCommonSenseName() {
return commonSenseName;
}
}
String columnName = "id of the client";
String targetFieldName = MappingEnum.fromAlias(columnName).getCommonSenseName();