绑定Map <k,v =“”>,其中K不是Java中的String </k,>

时间:2013-03-14 12:04:28

标签: java binding map

我在项目中使用BetterBeanBindings,如果我可以对其键不是String的Map进行绑定,那就太好了。

让我们举一个例子来解释这种情况:

public class Bean {
    // ...
    private Map<String, AnotherObject> mapOne;
    private Map<SomeObject, AnotherObject> mapTwo;
    // ...

    public Map<String, AnotherObject> getMapOne() {
        return this.mapOne;
    }

    public void setMapOne(Map<String, AnotherObject> mapOne) {
        Map<String, AnotherObject> oldMapOne = this.mapOne;
        this.mapOne = mapOne;
        this.propertyChangeSupport.firePropertyChange("mapOne", oldMapOne, mapOne);
    }

    public Map<SomeObject, AnotherObject> getMapTwo() {
        return this.mapTwo;
    }

    public void setMapTwo(Map<SomeObject, AnotherObject> mapTwo) {
        Map<SomeObject, AnotherObject> oldMapTwo = this.mapTwo;
        this.mapTwo = mapTwo;
        this.propertyChangeSupport.firePropertyChange("mapTwo", oldMapTwo, mapTwo);
    }

    // ...
}

BBB能够对其键为String的地图进行绑定(也可能超过数字,如果我记得正确的甚至不是原始类型,它有标准的解析)允许这样做:

Bean bean;
// ...
Bindings.createAutoBinding(UpdateStrategy.READ_WRITE
        bean, BeanProperty.create("mapOne.xxx"),
        whateverBean, whateverProperty);

这会将bean.getMapOne().get("xxx")的结果正确地绑定到第5和第4个参数中给定对象的给定属性,反之亦然。

但是,如果我们尝试使用mapTwo

Bindings.createAutoBinding(UpdateStrategy.READ_WRITE
        bean, BeanProperty.create("mapTwo.xxx"),
        whateverOtherOrNotBean, whateverOtherOrNotProperty);

绑定尝试解析bean.getMapTwo().get("xxx"),因为这是属性定义中提供的内容,mapTwo可能不是String,返回null。这是有道理的,因为绑定不必知道如何将String从属性转换为解析所需的对象

有没有选择这样做?使用转换器可能有某种解决方法吗?

1 个答案:

答案 0 :(得分:0)

我做了一个小的解决方法,对每个案例都不起作用,但是非常普遍。

事情是使用Map<K, V>,它能够响应KString类型的值,其中Map<String, V>支持主地图。

StringBackedMap:

import java.util.Map;
import java.util.Set;

public interface StringBackedMap<K, V> extends Map<K, V> {

    public V get(String key);

    public boolean containsKey(String key);

    public Set<Entry<String, V>> backerEntrySet();

    public Set<String> backerKeySet();

}

StringBackedHashMap:

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class StringBackedHashMap<K, V> extends HashMap<K, V> implements StringBackedMap<K, V> {

    private static final long serialVersionUID = 1L;

    private Map<String, V> backerMap;

    public StringBackedHashMap() {
        super();

        init();
    }

    public StringBackedHashMap(int capacity) {
        super(capacity);

        init();
    }

    public StringBackedHashMap(int capacity, float loadFactor) {
        super(capacity, loadFactor);

        init();
    }

    public StringBackedHashMap(Map<? extends K, ? extends V> map) {
        super(map);

        init();

        putAll(map);
    }

    private void init() {
        this.backerMap = new HashMap<String, V>();
    }

    @Override
    public V get(String key) {
        return this.backerMap.get(key);
    }

    @Override
    public V get(Object key) {
        V value = super.get(key);

        if (value == null) {
            value = this.backerMap.get(key.toString());
        }

        return value;
    }

    @Override
    public boolean containsKey(String key) {
        return this.backerMap.containsKey(key);
    }

    @Override
    public boolean containsKey(Object key) {
        return super.containsKey(key) || this.backerMap.containsKey(key);
    }

    @Override
    public Set<String> backerKeySet() {
        return this.backerMap.keySet();
    }

    @Override
    public Set<Entry<String, V>> backerEntrySet() {
        return this.backerMap.entrySet();
    }

    @Override
    public V put(K key, V value) {
        V oldValue = super.put(key, value);

        this.backerMap.put(key.toString(), value);

        return oldValue;
    }

    @Override
    public void putAll(Map<? extends K, ? extends V> map) {
        super.putAll(map);

        if ((map != null) && (!map.isEmpty())) {
            for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
                this.backerMap.put(entry.getKey().toString(), entry.getValue());
            }
        }
    }

    @Override
    public V remove(Object key) {
        V oldValue = super.remove(key);

        this.backerMap.remove(key.toString());

        return oldValue;
    }

    @Override
    public void clear() {
        super.clear();

        this.backerMap.clear();
    }

}