独一无二的对象

时间:2012-11-15 22:08:23

标签: java

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

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 个答案:

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