我的对象看起来像下面的
Store {
String shopId;
long distance;
}
我有商店的清单。
List<Store> storesList = Arrays.asList(
new Store (1, 1),
new Store (1, 5),
new Store (2, 2),
new Store (1, 1), // this is duplicate
new Store (1, 2),
new Store (1, 1), // this is duplicate
new Store (3, 7)
new Store (3, 5)
);
输出
Store {shopId=1, distance=1} // its fine to have any one among 3 duplicates
Store {shopId=2, distance=2}
Store {shopId=3, distance=5}
我可以像下面的
一样调用自己的distint方法private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Map<Object, Boolean> seen = new ConcurrentHashMap<>();
return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
并像这样过滤它
List<Store> stores= storesList .stream()
.filter(distinctByKey(pr -> Arrays.asList(pr.getShopId())))
.collect(toList());
但是如何同时以较小的距离对它进行过滤?
答案 0 :(得分:4)
storesList.stream()
.collect(Collectors.toMap(
Store::getShopId,
Function.identity(),
BinaryOperator.minBy(Comparator.comparingLong(Store::getDistance))
))
.values()
.forEach(System.out::println);
您可以合并这些相同的Store
(通过storeId
),您会说,合并时,您将在两个商店之间使用最小的distance
。
答案 1 :(得分:2)
如果按过滤器之前的距离对流进行排序,则得到的距离最小:
List<Store> stores = storesList.stream()
.sorted(Comparator.comparing(Store::getDistance))
.filter(distinctByKey(it -> it.shopId))
.collect(toList());
答案 2 :(得分:0)
您可以尝试以下方法:
Collection<Store> stores = storesList.stream()
.collect(Collectors.groupingBy(Store::getShopId,
Collectors.collectingAndThen(
Collectors.minBy(Comparator.comparingLong(Store::getDistance)),
Optional::get)))
.values();
在开始时,您将按shopId
进行分组,然后您使用的值为最小值distance
。在Ende,您只是使用此地图的值作为结果。
如果您需要列表而不是收藏夹,则可以使用
new ArrayList<>(stores);