如何生成由列表

时间:2017-05-05 11:21:00

标签: java collections wrapper

我有一个如下所示的数据模型:

class CustomField {
    String key;
    String value;
}

从我可以获得List<CustomField>实例的API。密钥在列表中是唯一的,这意味着此集合确实应该是Map<String, String>。在此列表上操作很麻烦,因为每个操作都需要迭代来检查现有密钥(CustomField不会实现等于)

如何创建Map<String, String>&#34;视图&#34;在此列表的支持下,我可以使用Map界面对其进行操作吗?

我想要一个通用方法,例如:<T, K, V> Map<K, V> createMapBackedByList(List<T> list, BiFunction<K, V, T> elementMapper, Function<T, K> keyMapper, Function<T, V> valueMapper)或类似的。

它将使用函数在列表元素和映射键和值之间进行映射。

这里重要的是我希望对地图的更改反映在基础列表中,这就是Streams API在这里不起作用的原因......

编辑:我无法修改API或CustomField类。

2 个答案:

答案 0 :(得分:3)

简单:

自己编写

 public class ListBackedMap<K, V> implements Map<K, V> {

在创作时需要某种List<Pair<K,V>>;并且&#34;推迟&#34;那个。当然,这要求您的CustomField类实现Pair接口。 (你可能也需要发明)

(或者:您的新课程extends AbstractMap<K,V>可以保护您的大部分工作)。

现在你的方法只返回一个这样的Map的实例。

换句话说:我不知道有一个符合您要求的内置包装器。但是自己实施一个应该是非常直接的。

编辑:鉴于OP无法更改CustomField类,这是一个简单的助手,例如

 interface <K, V> MapEntryAdapter {
   K getKey();
   V getValue();
 }

将是必需的;以及知道如何从CustomField的实例检索键/值的特定实现。在这种情况下,地图将由List<MapEntryAdapter<K, V>>支持。

答案 1 :(得分:1)

我最终尝试自己实现它并将其基于AbstractList。它实际上比我第一次更容易......

public class ListBackedMap<T, K, V> extends AbstractMap<K, V> {
    private final List<T> list;
    private final BiFunction<K, V, T> keyValueToElement;
    private final Function<T, K> elementToKey;
    private final Function<T, V> elementToValue;

    public ListBackedMap(List<T> list, BiFunction<K, V, T> keyValueToElement, Function<T, K> elementToKey, Function<T, V> elementToValue) {
        this.list = list;
        this.keyValueToElement = keyValueToElement;
        this.elementToKey = elementToKey;
        this.elementToValue = elementToValue;
    }

    @Override
    public Set<Entry<K, V>> entrySet() {
        return list.stream()
                .collect(toMap(elementToKey, elementToValue))
                .entrySet();
    }

    @Override
    public V put(K key, V value) {
        V previousValue = remove(key);
        list.add(keyValueToElement.apply(key, value));
        return previousValue;
    }

    public List<T> getList() {
        return list;
    }
}

它不是非常高性能(或线程安全),但它似乎做得很好。

示例:

List<CustomField> list = getList();
ListBackedMap<CustomField, String, String> map = new ListBackedMap<>(
        list,
        (key, value) -> new CustomField(key, value),
        CustomField::getKey,
        CustomField::getValue);