java - 映射集合元素并保留对源集合的引用

标签 java collections

我正在寻找一种创建集合、列表、集合或映射的方法,其中包含原始集合的转换元素并反射(reflect)该集合中的每个修改。

例如,如果我有一个 List<Integer>来自第三方 API,而另一个 API 需要 List<String> .我知道我可以像这样转换列表:

List<Integer> intList = thirdPartyBean.getIntListProperty();
List<String> stringList = intList.stream().map(Integer::toString)
    .collect(Collectors.toList());
secondBean.setStringListProperty(stringList);

问题是,如果其中一个列表发生任何变化,另一个列表仍将反射(reflect)之前的状态。让我们假设 intList包含 [1, 2, 3] :

intList.add(4);
stringList.remove(0);
System.out.println(intList.toString()); // will print: [1, 2, 3, 4]
System.out.println(stringList.toString()); // will print: [2, 3]
// Expected result of both toString(): [2, 3, 4]

所以我正在搜索类似 List.sublist(from, to) 的内容结果由原始列表“支持”。

我正在考虑实现我自己的列表包装器,它是这样使用的:

List<String> stringList = new MappedList<>(intList, Integer::toString, Integer::valueOf);

第二个 lambda 用于反转转换,以支持像 stringList.add(String) 这样的调用.

但在我自己实现之前,我想知道我是否尝试重新发明轮子 - 也许已经有针对此问题的通用解决方案?

最佳答案

我会将列表包装在另一个附有转换器的 List 中。

public class MappedList<S, T> extends AbstractList<T> {
    private final List<S> source;
    private final Function<S, T> fromTransformer;
    private final Function<T, S> toTransformer;

    public MappedList(List<S> source, Function<S, T> fromTransformer, Function<T, S> toTransformer) {
        this.source = source;
        this.fromTransformer = fromTransformer;
        this.toTransformer = toTransformer;
    }

    public T get(int index) {
        return fromTransformer.apply(source.get(index));
    }

    public T set(int index, T element) {
        return fromTransformer.apply(source.set(index, toTransformer.apply(element)));
    }

    public int size() {
        return source.size();
    }

    public void add(int index, T element) {
        source.add(index, toTransformer.apply(element));
    }

    public T remove(int index) {
        return fromTransformer.apply(source.remove(index));
    }

}

private void test() {
    List<Integer> intList = new ArrayList<>(Arrays.asList(1, 2, 3));
    List<String> stringList = new MappedList<>(intList, String::valueOf, Integer::valueOf);
    intList.add(4);
    stringList.remove(0);
    System.out.println(intList); // Prints [2, 3, 4]
    System.out.println(stringList); // Prints [2, 3, 4]
}

注意 fromTransformer 需要 null 检查输入值,如果 source 可能包含 null

现在您不是将原始列表转换为另一个列表并与原始列表失去联系,您是在向原始列表添加转换。

关于java - 映射集合元素并保留对源集合的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54928016/

相关文章:

java - Java Swing-如何在可见帧B时如何使用帧A?

c# int 数组哈希集的结构比较

java - 少量条目的 Java Map 最快实现

java - scala 中的 cogroup 两个 RDD

java - 虽然 mod 1 不是 0 Android

java - 如何检测 BlackBerry 设备的屏幕方向是 "natural"?

java - 为什么不更常用 Collections.checkedMap 和 friend ?

java - 更高级版本的 Collections.frequency()

java - 使用 Spring-boot 进行安全配置

java - 在调用类本身处理异常