Reputation: 16671
My object looks like following
Store {
String shopId;
long distance;
}
I got a list of stores.
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)
);
Output
Store {shopId=1, distance=1} // its fine to have any one among 3 duplicates
Store {shopId=2, distance=2}
Store {shopId=3, distance=5}
i can call my own distint method like following
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;
}
and filter it like this
List<Store> stores= storesList .stream()
.filter(distinctByKey(pr -> Arrays.asList(pr.getShopId())))
.collect(toList());
but how to filter it at the same time by smaller distance too ?
Upvotes: 3
Views: 99
Reputation: 11050
You can try this:
Collection<Store> stores = storesList.stream()
.collect(Collectors.groupingBy(Store::getShopId,
Collectors.collectingAndThen(
Collectors.minBy(Comparator.comparingLong(Store::getDistance)),
Optional::get)))
.values();
At the beginning you are grouping by shopId
, then you are using the value with the minimum distance
. At the Ende you are just using the values of this map as result.
If you need a List instead oft a Collection you can just use
new ArrayList<>(stores);
Upvotes: 0
Reputation: 120968
storesList.stream()
.collect(Collectors.toMap(
Store::getShopId,
Function.identity(),
BinaryOperator.minBy(Comparator.comparingLong(Store::getDistance))
))
.values()
.forEach(System.out::println);
You can merge these same Store
s (by storeId
), where you would say that when merging you would take the smallest distance
between two Stores.
Upvotes: 4
Reputation: 6859
If you sort the stream by distance before filter, you will get the smallest distances:
List<Store> stores = storesList.stream()
.sorted(Comparator.comparing(Store::getDistance))
.filter(distinctByKey(it -> it.shopId))
.collect(toList());
Upvotes: 2