Home > front end >  check if two lists of objects have the same value of an attribute
check if two lists of objects have the same value of an attribute

Time:12-31

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.

  •  Tags:  
  • java
  • Related