我想为某些属性创建一个独一无二的对象:
import java.util.HashMap;
public class SourceLanguage {
private final String name;
private static HashMap<String,SourceLanguage> existing;
private SourceLanguage(String name){
this.name = name;
}
public String getName(){
return name;
}
public static SourceLanguage get(String name){
if(existing==null){
existing = new HashMap<>();
SourceLanguage sl = new SourceLanguage(name);
existing.put(name.toLowerCase(),sl);
return sl;
}
SourceLanguage check = existing.get(name);
if(check==null){
SourceLanguage sl = new SourceLanguage(name);
existing.put(name.toLowerCase(),sl);
return sl;
}else {
return check;
}
}
}
我想将此类的对象用作另一个地图中的键。
我觉得这有点过分。 是否有更简单的方法来实现目标?
答案 0 :(得分:2)
您可以考虑使用Registry pattern。这样,SourceLanguage
对象的行为可以与强制执行其唯一性的行为分开。它们也可以彼此独立地变得更加复杂;注册表可以处理注释中描述的内存泄漏,而不会使SourceLanguage
类混乱。
将SourceLanguage
和Registry类放在同一个包中,但使SourceLanguage
类包-visibile(或给它一个protected
构造函数)然后外部组件将不会能够直接实例化SourceLanguage
并且必须通过注册表。
答案 1 :(得分:2)
我强烈建议您避免对缓存进行强引用。如果这是线程安全的话,你还需要一些同步。
public class SourceLanguage {
private final String name;
private final static Map<String, SoftReference<SourceLanguage>> cache
= new HashMap<String, SoftReference<SourceLanguage>>();
private SourceLanguage(String name){
this.name = name;
}
public String getName(){
return name;
}
public static SourceLanguage get(String name){
final String key = name.toLowerCase();
SourceLanguage lang = null;
synchronized (cache) {
SoftReference<SourceLanguage> ref = cache.get(key);
if (ref != null) {
lang = ref.get();
}
if (lang == null) {
SourceLanguage sl = new SourceLanguage(name);
cache.put(key, new SoftReference<SourceLanguage>(sl);
}
}
return lang;
}
}
答案 2 :(得分:1)
除非我遗漏了什么,否则我认为你可以做到这一点。
public class SourceLanguage {
private final String name;
private static HashMap<String,SourceLanguage> existing = new HashMap<String, SourceLanguage>();
private SourceLanguage(String name){
this.name = name;
}
public String getName(){
return name;
}
public static SourceLanguage get(String name){
SourceLanguage ret = existing.get(name.toLowerCase());
if(ret == null) {
ret = new SourceLanguage(name);
existing.put(name.toLowerCase(),ret);
}
return ret;
}
}
答案 3 :(得分:0)
您正在尝试的是实习的一般概念。一般来说,它很容易出现内存泄漏,但我怀疑在你的情况下这是一个问题,因为 很多语言。
我建议使用ConcurrentHashMap
:
private static final ConcurrentMap<String, SourceLanguage> existing =
new ConcurrentHashMap<>();
public static SourceLanguage get(String name) {
name = name.toLowerCase();
final SourceLanguage old = existing.get(name);
if (old != null) return old;
final SourceLanguage
created = new SourceLanguage(name),
justPut = existing.putIfAbsent(name, created);
return justPut != null? justPut : created;
}