Java 检索;“标准值”;从一个集合<;T>;其中T有一个自定义的等于()
我有一个Java 检索;“标准值”;从一个集合<;T>;其中T有一个自定义的等于(),java,set,Java,Set,我有一个类Foo,它正确地覆盖了equals()和hashCode() 我还想使用HashSet来跟踪“规范值”,例如,我有一个类,我想这样写,这样如果我有两个独立的对象是等价的,我可以将它们合并为对同一对象的引用: class Canonicalizer<T> { final private Set<T> values = new HashSet<T>(); public T findCanonicalValue(T value)
类Foo
,它正确地覆盖了equals()
和hashCode()
我还想使用HashSet
来跟踪“规范值”,例如,我有一个类,我想这样写,这样如果我有两个独立的对象是等价的,我可以将它们合并为对同一对象的引用:
class Canonicalizer<T>
{
final private Set<T> values = new HashSet<T>();
public T findCanonicalValue(T value)
{
T canonical = this.values.get(value);
if (canonical == null)
{
// not in the set, so put it there for the future
this.values.add(value);
return value;
}
else
{
return canonical;
}
}
}
我会使用如下的哈希映射:
final private Map<T, T> values = new HashMap<T, T>();
public T findCanonicalValue(T value)
{
T canon = this.values.get(value);
if (canon == null)
{
// not in the set, so put it there for the future
this.values.put(value, value);
return value;
}
else
{
// in the set
return canon;
}
}
final private Map value=new HashMap();
公共T findCanonicalValue(T值)
{
T canon=this.values.get(value);
如果(佳能==null)
{
//不在片场,所以把它放在未来
this.values.put(value,value);
返回值;
}
其他的
{
//现场
返回佳能;
}
}
它仍然有点笨拙,但它应该比映射和列表(少一个数据结构)稍微有效一些。映射似乎是正确的想法,但是为什么不从某个对象T映射到相应的规范对象呢
class Canonicalizer<T>
{
final private Map<T, T> values = new HashMap<T, T>();
public T findCanonicalValue(T value)
{
T canonical = this.values.get(value);
if (canonical == null)
{
// not in the map, so put it there for the future
this.values.put(value, value);
return value;
}
else
{
return canonical;
}
}
}
类规范化器
{
最终私有映射值=新HashMap();
公共T findCanonicalValue(T值)
{
T canonical=this.values.get(value);
if(规范==null)
{
//不在地图上,所以把它放在未来
this.values.put(value,value);
返回值;
}
其他的
{
返回规范;
}
}
}
使用番石榴的实习生
:
这正是它的用途。使用ConcurrentMap,它更简单一些。(和线程安全)
私有最终ConcurrentMap值=新ConcurrentHashMap();
公共T findCanonicalValue(T值){
值。putIfAbsent(值,值);
返回值。获取(值);
}
在许多情况下,您希望这种容器用于需要由不同线程访问的对象缓存;如果是这样,请确保不要忽略并发性问题,并注意线程安全映射实现通常不支持空键。如果出于某种原因您不能使用番石榴,请至少看一下源代码:
公共期末班实习生{
私有内部用户(){}
/**
*返回一个新的线程安全interner,该interner保留对
*它所拘留的每个实例,从而防止这些实例被
*垃圾已收集。如果此保留是可接受的,则此实现可能
*性能优于{@link#newWeakInterner}。
*/
公共静态Interner newStrongInterner(){
最终ConcurrentMap=new MapMaker().makeMap();
返回新的Interner(){
公共电子实习生(电子样本){
E canonical=map.putIfAbsent(checkNotNull(sample),sample);
return(canonical==null)?示例:canonical;
}
};
}
HashSet实际上在内部使用了一个HashMap,它将每个键的值设置为一个虚拟对象,因此如果需要使用get,最好使用map。
class Canonicalizer<T>
{
final private Map<T, T> values = new HashMap<T, T>();
public T findCanonicalValue(T value)
{
T canonical = this.values.get(value);
if (canonical == null)
{
// not in the map, so put it there for the future
this.values.put(value, value);
return value;
}
else
{
return canonical;
}
}
}
private final ConcurrentMap<T, T> values = new ConcurrentHashMap<T, T>();
public T findCanonicalValue(T value) {
values.putIfAbsent(value, value);
return values.get(value);
}
public final class Interners {
private Interners() {}
/**
* Returns a new thread-safe interner which retains a strong reference to
* each instance it has interned, thus preventing these instances from being
* garbage-collected. If this retention is acceptable, this implementation may
* perform better than {@link #newWeakInterner}.
*/
public static <E> Interner<E> newStrongInterner() {
final ConcurrentMap<E, E> map = new MapMaker().makeMap();
return new Interner<E>() {
public E intern(E sample) {
E canonical = map.putIfAbsent(checkNotNull(sample), sample);
return (canonical == null) ? sample : canonical;
}
};
}