我需要在地图地图中搜索并返回此元素所属的键。 我觉得这个实现很慢,你能帮我优化一下吗? 我需要使用TreeSet,我不能使用contains因为他们使用compareTo,而equals / compareTo对是以不兼容的方式实现的,我无法改变它。 (对不起,我的英文不好)
Map<Key, Map<SubKey, Set<Element>>> m = new TreeSet();
public String getKeys(Element element) {
for(Entry<Key, Map<SubKey, Set<Element>>> e : m.entrySet()) {
mapSubKey = e.getValue();
for(Entry<SubKey, Set<Element>> e2 : mapSubKey.entrySet()) {
setElements = e2.getValue();
for(Element elem : setElements)
if(elem.equals(element)) return "Key: " + e.getKey() + " SubKey: " + e2.getKey();
}
}
}
答案 0 :(得分:6)
这里的问题是键和值是向后的。
地图允许用户有效地找到与密钥相关联的值(Key
和SubKey
)(在此示例中为Element
)。
倒退很慢。
有双向地图实施,例如支持两个方向更快访问的Google Collections BiMap,,但这意味着要替换TreeMap
。否则,维护两个地图,每个方向一个。
答案 1 :(得分:1)
如果您无法使用contains
,并且您使用了地图地图,那么您唯一真正的选择就是迭代,就像您正在做的那样。
或者,您可以在单独的地图中保留Element
到Key/SubKey
的反向地图,这样可以更快地进行反向查找。
另外,如果您不确定某个地方只能存在给定的Element
,您可能希望存储和检索List<Element>
而不仅仅是Element
答案 2 :(得分:1)
当TreeMap和TreeSet以彼此兼容的方式实施时,compareTo和equals正常工作。此外,在Map中搜索时,只有搜索密钥才有效(对于TreeMap O(log n))。在Map中搜索值时,复杂性将变为线性。
有一种方法可以在内部TreeSet中优化搜索,但是在为Element类型实现自己的Comparator时。这样,您可以实现自己的compareTo方法,而无需更改Element对象本身。
答案 3 :(得分:0)
这是一个双向TreeMap(或TreeMap上的Bijection)。
它关联两个连接在一起的重载TreeMaps。
每个“反向”常量字段指向另一个TreeMap。一个TreeMap上的任何更改都会自动反映在其反向上。
因此,每个值都是唯一的。
public class BiTreeMap<K, V> extends TreeMap<K, V> {
public final BiTreeMap<V, K> inverse;
private BiTreeMap(BiTreeMap inverse) {
this.inverse = inverse;
}
public BiTreeMap() {
inverse = new BiTreeMap<V, K>(this);
}
public BiTreeMap(Map<? extends K, ? extends V> m) {
inverse = new BiTreeMap<V, K>(this);
putAll(m);
}
public BiTreeMap(Comparator<? super K> comparator) {
super(comparator);
inverse = new BiTreeMap<V, K>(this);
}
public BiTreeMap(Comparator<? super K> comparatorK, Comparator<? super V> comparatorV) {
super(comparatorK);
inverse = new BiTreeMap<V, K>(this, comparatorV);
}
private BiTreeMap(BiTreeMap<V, K> inverse, Comparator<? super K> comparatorK) {
super(comparatorK);
this.inverse = inverse;
}
@Override
public V put(K key, V value) {
if(key == null || value == null) {
throw new NullPointerException();
}
V oldValue = super.put(key, value);
if (oldValue != null && inverse._compareKeys(value, oldValue) != 0) {
inverse._remove(oldValue);
}
K inverseOldKey = inverse._put(value, key);
if (inverseOldKey != null && _compareKeys(key, inverseOldKey) != 0) {
super.remove(inverseOldKey);
}
return oldValue;
}
private int _compareKeys(K k1, K k2) {
Comparator<? super K> c = comparator();
if (c == null) {
Comparable<? super K> ck1 = (Comparable<? super K>) k1;
return ck1.compareTo(k2);
} else {
return c.compare(k1, k2);
}
}
private V _put(K key, V value) {
return super.put(key, value);
}
@Override
public V remove(Object key) {
V value = super.remove(key);
inverse._remove(value);
return value;
}
private V _remove(Object key) {
return super.remove(key);
}
@Override
public void putAll(Map<? extends K, ? extends V> map) {
for (Map.Entry<? extends K, ? extends V> e : map.entrySet()) {
K key = e.getKey();
V value = e.getValue();
put(key, value);
}
}
@Override
public void clear() {
super.clear();
inverse._clear();
}
private void _clear() {
super.clear();
}
public boolean containsValue(Object value) {
return inverse.containsKey(value);
}
@Override
public Map.Entry<K, V> pollFirstEntry() {
Map.Entry<K, V> entry = super.pollFirstEntry();
inverse._remove(entry.getValue());
return entry;
}
@Override
public Map.Entry<K, V> pollLastEntry() {
Map.Entry<K, V> entry = super.pollLastEntry();
inverse._remove(entry.getValue());
return entry;
}
}