Remove Duplicates from a List of Objects Based on Property in Java 8

Java stream remove duplicate list of objects of list property

We need something like "distinct" which is kind of like a stateful filter. So we can create our own filter having its own state of previously seen pairs of cities/countries. This can be achieved with having a filter with its own Set:

public static <T> Predicate<T> distinctAddress() {
Set<Object> seen = ConcurrentHashMap.newKeySet();
return t -> {
boolean r = ((Obj1)t).getAddress().stream().map((a) -> seen.contains(new AbstractMap.SimpleImmutableEntry<>(a.getCity(), a.getCountry()))).anyMatch((b) -> b);
((Obj1)t).getAddress().stream().forEach((a) -> seen.add(new AbstractMap.SimpleImmutableEntry<>(a.getCity(), a.getCountry())));
return !r;
};
}

List<Obj1> list = obj1s.stream().filter(distinctAddress()).collect(Collectors.toList());

Edit:
I just realized you mention an address will always be unique inside an address list. In that case you can shorten the Predicate as so (as you wouldn't already have it in the Set because of the same list):

public static <T> Predicate<T> distinctAddress() {
Set<Object> seen = ConcurrentHashMap.newKeySet();
return t -> ((Obj1)t).getAddress().stream().map((a) -> seen.add(new AbstractMap.SimpleImmutableEntry<>(a.getCity(), a.getCountry()))).filter((e) -> e).count() > 0;
}

List<Obj1> list = obj1s.stream().filter(distinctAddress()).collect(Collectors.toList());

Remove duplicates from a list of objects based on different case String property in Java 8

John and JOHN are different Strings, use a case insensitive Comparator

 Comparator.comparing(Employee::getName, String.CASE_INSENSITIVE_ORDER)

Remove duplicates from a list of objects based multiple attributes in Java 8

As far as I understood, you want to remove elements only if they are a duplicate and their getVode method returns false.

We can do this literally. First, we have to identify which elements are duplicates:

Map<Object, Boolean> isDuplicate = productsList.stream()
.collect(Collectors.toMap(pm -> Arrays.asList(pm.getCode(), pm.getMode()),
pm -> false, (a, b) -> true));

Then, remove those fulfilling the condition:

productsList.removeIf(pm -> !pm.getVode()
&& isDuplicate.get(Arrays.asList(pm.getCode(), pm.getMode())));

Or, not modifying the old list:

List<ProductModel> uniqueProducts = new ArrayList<>(productsList);
uniqueProducts.removeIf(pm -> !pm.getVode()
&& isDuplicate.get(Arrays.asList(pm.getCode(), pm.getMode())));

which can also be done via Stream operation:

List<ProductModel> uniqueProducts = productsList.stream()
.filter(pm -> pm.getVode()
|| !isDuplicate.get(Arrays.asList(pm.getCode(), pm.getMode())))
.collect(Collectors.toList());

Remove duplicates based on property and predicate in Java 8

How about this,

Collection<Employee> distinctEmps = employee.stream()
.collect(Collectors.toMap(Employee::getId, Function.identity(),
(e1, e2) -> e1.getIq() >= e2.getIq() ? e1 : e2))
.values();

Another variant by merely following @Holgers approach would be,

Collection<Employee> distinctEmps = employee.stream()
.collect(Collectors.toMap(Employee::getId, Function.identity(),
BinaryOperator.maxBy(Comparator.comparing(Employee::getIq))))
.values();


Related Topics



Leave a reply



Submit