如何生成由列表支持的地图

How to generate a Map backed by a List

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

class CustomField {
    String key;
    String value;
}

从 API 我可以获得 List<CustomField> 的实例。键在列表中是唯一的,这意味着这个集合确实应该是一个Map<String, String>。在此列表上操作很痛苦,因为每个操作都需要迭代来检查现有键(CustomField 也没有实现 equals)

如何创建一个由该列表支持的 Map<String, String> "view",以便我可以使用 Map 接口对其进行操作?

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

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

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

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

简单:

自己写

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

创建时需要某种 List<Pair<K,V>>; "defers" 到那个。当然,这需要您的 CustomField class 实现 Pair 接口。 (你可能也需要发明)

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

现在您的方法只是 return 此类 Map 的一个实例。

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

编辑:考虑到 OP 无法更改 CustomField class,一个简单的助手,例如

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

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

我最终尝试自己实现它并将其基于 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);