How can I duplicate the same items in list, change property values and add it to new list?

Viewed 121

I have a list of items that have an action. Currently, action property is set to null. What I want to do is copy the items in the list, change its action property to delete string and add it to a new list. I want to do it again with add. So the idea is to have list of same items but one with action delete and another with action add.

So have a list with items like this:

{
            "someNumber": "123456",
            "projectName": "Foo Bar",
            "action": "delete"
        },
     {
            "someNumber": "454546",
            "projectName": "Foo Bar",
            "action": "delete"
        },
     {
            "someNumber": "123456",
            "projectName": "Foo Bar",
            "action": "add"
        },
     {
            "someNumber": "454546",
            "projectName": "Foo Bar",
            "action": "add"
        }

Where I duplicated the 2 items above that initially had action = null but now there's one for delete and add.

I have this code snippet here:

List<Leader> leadersToDeleteForUpdating = newLeaders.stream().filter(l-> !"add".equals(l.getAction()) && l.getEndDate() == null).collect(toList());
leadersToDeleteForUpdating.forEach(l->l.setAction("delete"));

List<Leader> leadersToAddForUpdating = newLeaders.stream().filter(l-> !"add".equals(l.getAction()) && l.getEndDate() == null).collect(toList());
leadersToAddForUpdating.forEach(l->l.setAction("add"));

List<Leader> leadersToDeleteAndAddForUpdating = new ArrayList<>(leadersToDeleteForUpdating);
leadersToDeleteAndAddForUpdating.addAll(leadersToAddForUpdating);

Right now, it's overriding the item values with action = add and the action = delete items are not copied over. What am I doing wrong in this case?

1 Answers

The reason why you are getting all items with add is because you are modifying the same objects all the time. So you have two objects, to the same two objects you first set the action to delete, and then you set it to add. So by the time you add both lists, both lists are the same, so you end up with 4 items with add (if you started with two).

A simple way would be to clone these objects, and call that clone on each of them when you're streaming the lists, like this:

public class Leader {
    private String someNumber;
    private String projectName;
    private String action;

    public Leader(String someNumber, String projectName, String action) {
        this.someNumber = someNumber;
        this.projectName = projectName;
        this.action = action;
    }

    public Leader clone() {
        return new Leader(this.getSomeNumber(), this.getProjectName(), this.getAction());
    }
}

And then when you're streaming, map and clone them:

List<Leader> leadersToDeleteForUpdating = newLeaders.stream().map(l-> l.clone()).filter(l-> !"add".equals(l.getAction())).collect(Collectors.toList());
leadersToDeleteForUpdating.forEach(l->l.setAction("delete"));

List<Leader> leadersToAddForUpdating = newLeaders.stream().map(l-> l.clone()).filter(l-> !"add".equals(l.getAction())).collect(Collectors.toList());
leadersToAddForUpdating.forEach(l->l.setAction("add"));

If you want to do this in a more conventional way, you could use the Cloneable interface: https://www.geeksforgeeks.org/cloneable-interface-in-java/

Related