java集合:使用映射值进行过滤,然后返回初始值

时间:2015-10-09 08:50:51

标签: java collections java-8

是否有一种简短而优雅的方式来反转映射功能?

问题是这样的:我有一堆类型为A的对象,我需要映射到类型B,对B对象执行过滤,然后返回到相应的A对象。

提供一些细节和示例: 我有一个批量过滤功能

Collection<CarVO> myFilter(Collection<CarVO> originalCollection);

Collection<Car> cars,最后是映射方法Car#toVO()。 我想出了这段代码:

Collection<Car> filtered = cars.stream()
    .filter(car -> !myFilter(Collections.singleton(car)).isEmpty())
    .collect(toList());

但我怀疑这个效率不高,因为我逐个过滤对象。 其他方式做同样的事情:

Map<Car, CarVO> map = new HashMap<>();
for (Car car : cars) map.put(car, car.toVO());
Collection<CarVO> filteredVOs = myFilter(map.values());
cars = cars.stream.filter(car -> filteredVOs.contains(map.get(car))).collect(toList());

但我不想明确地建造地图。

UPD:谢谢大家, 不知道Map.values()返回了实时视图。我会坚持使用retainAll()

2 个答案:

答案 0 :(得分:2)

由于您的方法myFilter(Collection<CarVO>)必须决定是否应删除每个元素,并且您认为即使对于单元素集合也是如此,因此必须能够将逻辑提取到单个元素中-item Predicate。使用该提取的谓词将是最有效的解决方案。

但是,如果您不能这样做并且无论出于何种原因使用此现有方法,您可以按如下方式使用它:

Map<Car, CarVO> map = new HashMap<>();
for(Car car: cars) map.put(car, car.toVO());
map.values().retainAll(myFilter(map.values()));
Set<Car> filtered=map.keySet();

如果您确实需要列表,可以用

替换最后一行
List<Car> filtered=new ArrayList<>(map.keySet());

请注意,这假设myFilter返回一个新集合。如果通过从中删除元素将过滤器直接应用于其集合参数,则可以将map.values().retainAll(myFilter(map.values()));替换为myFilter(map.values());

答案 1 :(得分:0)

对一辆车使用Predicate

在谓词中,您可以在CarVO中转换汽车(如果需要),然后应用单个元素的逻辑。

为了DRY原则,你应该在原始的myFilter方法中使用这个谓词。