Java实现基于原列表实时转换的封装列表的方案咨询
Java 列表实时转换视图实现方案
需求本质是要获取原列表的转换视图,而非静态副本,所有操作都直接代理到原列表,仅在元素访问时做实时转换。
无第三方库的原生实现
Java 集合框架已经提供了抽象类AbstractList,仅需要实现少量核心方法就能快速得到可用的List实现,不需要重写全部List接口方法:
- 只读场景:仅实现
size()和get(int index)两个方法即可 - 可写场景:额外实现
set、add、remove等修改类方法即可
通用泛型实现代码如下:
import java.util.AbstractList; import java.util.List; import java.util.function.Function; public class MappedList<F, T> extends AbstractList<T> { private final List<F> sourceList; private final Function<F, T> mapper; // 可写场景需要的反向转换函数,只读场景可以移除 private final Function<T, F> reverseMapper; // 只读场景构造函数 public MappedList(List<F> sourceList, Function<F, T> mapper) { this(sourceList, mapper, null); } // 可写场景构造函数 public MappedList(List<F> sourceList, Function<F, T> mapper, Function<T, F> reverseMapper) { this.sourceList = sourceList; this.mapper = mapper; this.reverseMapper = reverseMapper; } @Override public int size() { return sourceList.size(); } @Override public T get(int index) { // 每次访问实时转换原列表元素 return mapper.apply(sourceList.get(index)); } // 可写场景需要重写的方法,只读场景可以删除 @Override public T set(int index, T element) { if (reverseMapper == null) throw new UnsupportedOperationException("只读视图不支持修改"); F oldValue = sourceList.set(index, reverseMapper.apply(element)); return mapper.apply(oldValue); } @Override public void add(int index, T element) { if (reverseMapper == null) throw new UnsupportedOperationException("只读视图不支持修改"); sourceList.add(index, reverseMapper.apply(element)); } @Override public T remove(int index) { return mapper.apply(sourceList.remove(index)); } }
使用示例:
List<Integer> intList = new ArrayList<>(List.of(1,2,3)); // 生成Integer转String的只读视图 List<String> strView = new MappedList<>(intList, String::valueOf); // 原列表修改后视图立刻同步 intList.add(4); System.out.println(strView.get(3)); // 输出4,实时生效
第三方库实现(Guava)
Guava 已经内置了开箱即用的转换视图能力,Lists.transform返回的就是原列表的转换视图,没有额外拷贝,所有原列表的修改都会实时同步到转换后的列表,用法非常简洁:
import com.google.common.collect.Lists; List<Integer> intList = new ArrayList<>(List.of(1,2,3)); // 直接生成转换视图 List<String> strView = Lists.transform(intList, String::valueOf); intList.add(4); System.out.println(strView.get(3)); // 输出4,实时同步
注意事项
- 两种实现都是懒转换,只有访问元素的时候才会执行转换逻辑,没有预转换的性能开销
- 转换视图本身不存储元素,内存占用极低
- 如果转换逻辑计算成本很高,要注意重复访问同一个元素会重复执行转换逻辑,有需要可以自行添加缓存层
内容的提问来源于stack exchange,提问作者pro100kryto
相关产品推荐
相关产品推荐

