I have two lists of objects localList and remotList, both lists have a consent attribute
I want to check the value of the consent attribute if the same for both lists
If Not, I want to remove all objects from localList don't have same consent value that exists in remotList and add all objects have same consent value that exist in remotList and not in localList
I implemented this solution but I want to improve it
Java Example
class Customer{
private Long id;
private String name;
private Integer consent;
public Customer(Long id, String name, Integer consent) {
this.id = id;
this.name = name;
this.consent = consent;
}
public Integer getConsent() {
return consent;
}
@java.lang.Override
public java.lang.String toString() {
return "Customer{"
"id=" id
", name='" name '\''
", consent=" consent
'}';
}
}
public static void main(String[] args) {
List<Customer> localList = new ArrayList<>();
localList.add(new Customer(1L, "name1", 12));
localList.add(new Customer(2L, "name2", 13));
localList.add(new Customer(3L, "name3", 14));
localList.add(new Customer(4L, "name4", 15));
List<Customer> remoteList = new ArrayList<>();
remoteList.add(new Customer(10L, "name1", 12));
remoteList.add(new Customer(11L, "name2", 11));
remoteList.add(new Customer(12L, "name3", 14));
remoteList.add(new Customer(13L, "name4", 16));
Map<Integer, Customer> map = remoteList.stream()
.collect(Collectors.toMap(s -> s.getConsent() , s -> s));
Map<Integer, Customer> map2 = localList.stream()
.collect(Collectors.toMap(s -> s.getConsent() , s -> s));
List<Customer> remove = new ArrayList<>();
localList.forEach(e -> {
if(map.get(e.getConsent()) == null ) {
remoteList.add(e);
}
});
remoteList.forEach(e -> {
if(map2.get(e.getConsent()) == null ) {
remove.add(e);
}
});
remove.forEach(e -> remoteList.remove(e));
remoteList.forEach(System.out::println);
the remoteList
Customer{id=10, name='name1', consent=12}
Customer{id=11, name='name2', consent=11}
Customer{id=12, name='name3', consent=14}
Customer{id=13, name='name4', consent=16}
the localList
Customer{id=1, name='name1', consent=12}
Customer{id=2, name='name2', consent=13}
Customer{id=3, name='name3', consent=14}
Customer{id=4, name='name4', consent=15}
Result
Customer{id=10, name='name1', consent=12}
Customer{id=12, name='name3', consent=14}
Customer{id=2, name='name2', consent=13}
Customer{id=4, name='name4', consent=15}
CodePudding user response:
For the first part, you can create a map for the remoteList
mapping each customer by name
. We are doing this for being able to search the remote customers faster.
Map<String, Customer> customerByName = remoteList.stream()
.collect(Collectors.toMap(Customer::getName, customer -> customer));
localList.removeIf(customer -> !Objects.equals(customer.getConsent(),
customerByName.get(customer.getName()).getConsent()));
Please note, the Customer
class would require a getter for the name
.
For the second part, we can also create a map for the localList
as we've done previously. We iterate through the remoteList
and filter each element which does not exist in the localList
(at least I believe this is what you would want to accomplish).
Map<String, Customer> localCustomerByName = localList.stream()
.collect(Collectors.toMap(Customer::getName, customer -> customer));
localList.addAll(remoteList.stream()
.filter(customer -> !localCustomerByName.containsKey(customer.getName()))
.collect(Collectors.toList()));
CodePudding user response:
Map<Integer, Customer> map = remoteList.stream()
.collect(Collectors.toMap(s -> s.getConsent() , s -> s));
List<Customer> hasDiffLastItem = localList.stream()
.filter(s -> !map.get(getConsent).getConsent().equals(s.getConsent()))
.collect(Collectors.toList());
CodePudding user response:
Here is one way. I used a linked list since they are more efficient at deleting items.
- first, create a comparator for a set. The tree set will take a comparator in place of an equals implementation.
- then iterate over the remote list, removing items if they appear in the local set.
- then iterate over the local list, removing items if they don't appear in the remote set.
Set<Customer> remoteSet = new TreeSet<>(comp);
Set<Customer> localSet = new TreeSet<>(comp);
remoteSet.addAll(remoteList);
localSet.addAll(localList);
Iterator<Customer> iter = localList.iterator();
while(iter.hasNext()) {
Customer s = iter.next();
if (remoteSet.contains(s)) {
iter.remove();
}
}
iter = remoteList.iterator();
while(iter.hasNext()) {
Customer s = iter.next();
if (!localSet.contains(s)) {
iter.remove();
}
}
You can combine the lists however you want but here are the results back to back.
localList.forEach(System.out::println);
remoteList.forEach(System.out::println);
prints
Customer{id=2, name='name2', consent=13}
Customer{id=4, name='name4', consent=15}
Customer{id=10, name='name1', consent=12}
Customer{id=12, name='name3', consent=14}
I tried different values using both your and my methods and the output was the same. I would recommend you check it yourself as I wasn't completely certain how you wanted this to work.