我正在寻找一种创建集合、列表、集合或映射的方法,其中包含原始集合的转换元素并反射(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/