0

我想为某些属性创建一个独一无二的对象:

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;
        }
    }
}

我想将此类的对象用作另一个地图中的键。

我觉得有点矫枉过正。有没有更简单的方法来实现目标?

4

4 回答 4

2

您可以考虑使用注册表模式。这样,SourceLanguage对象的行为可以与强制其唯一性的行为分开。它们也可能变得更复杂,彼此独立;注册表可以处理注释中描述的内存泄漏,而不会使您的SourceLanguage课程混乱。

SourceLanguage和 Registry 类放在同一个包中,但是使SourceLanguage类包可见(或给它一个protected构造函数),然后外部组件将无法SourceLanguage直接实例化,并且必须通过 Registry。

于 2012-11-15T22:13:48.553 回答
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;
    }
}
于 2012-11-15T22:27:58.703 回答
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;
    }
}
于 2012-11-15T22:15:48.500 回答
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;
}
于 2012-11-15T22:29:16.307 回答