Java O(1)中的getKey(B)与一对一映射数据结构(A,B)?
这个问题最初措辞错误,请参见下面的编辑。我将留待上下文讨论 我一直在思考构建双射(即一对一)映射的智能方法。映射函数a->B(多对一)基本上就是HashMap(a,B)所做的。如果我现在想要一个数据结构,在O(1)中实现一对一的contains(),那么java标准库中是否有我可以使用的东西?请注意,我现在什么都不需要这个,这只是我最近考虑过的事情,无法为它提供数据结构,所以答案并不仓促。有这样的课吗?如果没有,你认为这是什么原因 我能找到的只有关于hibernate的东西,这对我毫无帮助 编辑: 我的问题措词不当,因此需要作一些解释 我的意思是“向后”映射B->A。HashMap(A,B)在O(1)中包含(A)和(B),所以这甚至不是我的意思,很抱歉混淆了。我的意思是,是否有一个数据结构映射AB,在O(1)中有getValue(a)和getKey(B)Java O(1)中的getKey(B)与一对一映射数据结构(A,B)?,java,contains,one-to-one,Java,Contains,One To One,这个问题最初措辞错误,请参见下面的编辑。我将留待上下文讨论 我一直在思考构建双射(即一对一)映射的智能方法。映射函数a->B(多对一)基本上就是HashMap(a,B)所做的。如果我现在想要一个数据结构,在O(1)中实现一对一的contains(),那么java标准库中是否有我可以使用的东西?请注意,我现在什么都不需要这个,这只是我最近考虑过的事情,无法为它提供数据结构,所以答案并不仓促。有这样的课吗?如果没有,你认为这是什么原因 我能找到的只有关于hibernate的东西,这对我毫无帮助 编辑
我意识到这可以通过两个HashMap(A,B)和(B,A)来实现,它们被维护为包含相同的关系,但我觉得应该有一个数据结构来处理它,而不必“手动”进行处理,如果你有一个完美的散列函数,你可以使用散列映射作为一对一的映射。如果我了解你在做什么,以下内容就足够了:
Map<String,Object> map = new HashMap<String,Object>();
Map Map=newhashmap();
我不知道现有的类对containsKey和containsValue都执行O(1)操作,但是您可以通过扩展HashMap来完成,这样在插入时,您可以将每个值添加到内部HashSet中。重载containsValue以查找HashSet中的值。标准HashMap有O(1)containsKey,但O(n)containsValue
同样,可以在insert中强制执行1:1并检查现有值
请注意,如果发生大量冲突,最坏的情况下,哈希集查找可以达到O(n)。我认为您不会比两个哈希映射做得更好。编写包装器接口非常简单:
class OneToOneMap<Key, Value> {
public void add(Key k, Value v) {
if (!keyToVal_.contains(k) && !valToKey_.contains(v)) {
keyToVal_.add(k, v);
valToKey_.add(v, k);
}
}
private HashMap<K, V> keyToVal_;
private HashMap<V, K> valToKey_;
}
class-OneToOneMap{
公共无效添加(键k,值v){
如果(!keyToVal_uu.contains(k)&&!valToKey_uu.contains(v)){
keyToVal添加(k,v);
瓦尔托克伊加(v,k);
}
}
私有HashMap keyToVal;
私有HashMap valToKey_;
}
我不确定这是否是有效的Java,但你明白了。如果你愿意使用第三方库,Guava也提供了一个很好的API。它不是一个
getKey
方法,而是提供一个inverse()
视图,返回一个BiMap
。(当然,它确实提供了恒定的时间containsValue
)
目前,
HashBiMap
基本上是内部两个保持同步的HashMap
——尽管它在如何保持它们之间的匹配方面非常一致——但实现在未来可能会变得更智能。我也有同样的需求,并提出了这个可能有用的BiMap。它只使用一个hashmap并返回一个entry对象,这样可以为返回值指定一个特定的类型,并允许映射为null
public class BiMap<T1, T2>
{
public static class Entry<T1, T2>
{
public final T1 item1;
public final T2 item2;
public Entry( T1 item1, T2 item2 )
{
this.item1 = item1;
this.item2 = item2;
}
}
private final HashMap< Object, Entry<T1, T2> > mappings = new HashMap<>();
private int loopedLinkCount;
public void put( T1 item1, T2 item2 )
{
remove(item1);
remove(item2);
Entry<T1, T2> entry = new Entry<T1, T2>( item1, item2 );
mappings.put( item1, entry );
mappings.put( item2, entry );
if( Objects.equals(item1, item2) ){
loopedLinkCount++;
}
}
/**
*
* @param key
* @return an entry containing the key and it's one to one mapping or null if there is
* no mapping for the key.
*/
public Entry<T1, T2> get( Object key )
{
return mappings.get( key );
}
public Entry<T1, T2> remove( Object key )
{
Entry<T1, T2> entry = mappings.remove( key );
if( entry == null ){
return null;
}
if( Objects.equals( entry.item2, entry.item1 ) ){
loopedLinkCount--;
return entry;
}
return mappings.remove( Objects.equals( key, entry.item1 ) ? entry.item2 : entry.item1 );
}
public Set< Entry<T1, T2> > entrySet()
{
return new HashSet<>( mappings.values() );
}
public int size()
{
return ( mappings.size() + loopedLinkCount ) / 2;
}
}
公共类BiMap
{
公共静态类条目
{
公共最终T1项目1;
公共最终项目2;
公共入口(T1项目1、T2项目2)
{
这个项目1=项目1;
本条第2项=第2项;
}
}
私有最终HashMap
是否只需扩展类A并添加一个返回B的属性就可以了?那么,如果HashMap不这样做,您想要什么呢?它可以用于一对一映射。@PeterLawrey是java O(1)中的HashMap.contains?您是否在寻找一对一映射上的约束,因为HashMap可以用于一对一映射,并且有一个选择充分的哈希函数和一个足够小的集合,在摊销O(1)中有contains.我才意识到我的问题并不能真正表达我的愿望;编辑。这不限于1对1的映射。许多键可以具有相同的值。编辑:我错了…@BlackPlanet不正确。如果你仔细阅读我的回答,我说的是完美的散列函数,对不起。我读得不够仔细。你完全正确+1因为它回答了我最初的问题,正如我意识到的那样,这个问题的措辞并不是我真正想问的。但是是的,一个完美的散列函数可以保证键和值之间的一对一关系,谢谢!可以肯定的是,两个HashMap将满足O(1)访问的要求,一个是映射A->B,另一个是映射B->A