Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 List copy [duplicate]

I have an employee object

I Cannot update the employee Object

public class Employee {

    public Employee(Integer id, Integer age, String gender, String fName, String lName) {
        this.id = id;
        this.age = age;
        this.gender = gender;
        this.firstName = fName;
        this.lastName = lName;
    }

    private Integer id;
    private Integer age;
    private String gender;
    private String firstName;
    private String lastName;

I am initially setting a employee list but want to create copy of that and then make changes to it. Even though I am creating new list its still changing the original list

public class ListTest {

    public static void main(String[] args) {

        List<Employee> employeeList = new ArrayList<>();
        Employee employee = new Employee(1, 1, "MALE", "TEST", "TEST");
        employeeList.add(employee);

        List<Employee> listTwo = new ArrayList<>();
        listTwo.addAll(employeeList);

        listTwo.get(0).setAge(11);

        System.out.println(employeeList.get(0).getAge());

    }
}

The output is coming as 11.

Is there any easier way to clone from original list and any changes should not be applied to original list object and just the new list I created

like image 449
Makky Avatar asked Dec 15 '17 13:12

Makky


3 Answers

First make a copy constructor in your Employee class:

    public Employee(Employee employee) {
        this.id = employee.id;
        this.age = employee.age;
        this.gender = employee.gender;
        this.firstName = employee.firstName;
        this.lastName = employee.lastName;
    }

And then you can make a deep copy with Java 8 streams:

List<Employee> listTwo = employeeList.stream().map(item -> new Employee(item)).collect(Collectors.toList());
like image 98
Planck Constant Avatar answered Oct 10 '22 23:10

Planck Constant


It is not changing the original list, but it is changing the object which is contained in both lists.

In cases like this, it might be very useful to make the employee objects unmodifiable and provide a possibility to create a copy object with changed properties with respect to the original one.

If you absolutely cannot modify the Employee object (not even add a copy constructor), you instead can implement an own copy/clone method (not connected to the Cloneable interface, which is said to be broken):

public static Employee clone_employee(Employee original) {
    return new Employee(original.getID(), original.getAge(), original.getGender(), original.getFirstName(), original.getLastName());
}

and then do

employeeList.stream()
    .map(item -> clone_employee(item))
    .collect(Collectors.toList());

or just

employeeList.stream()
    .map(<thisclassname>::clone_employee)
    .collect(Collectors.toList());

(essentially the same what Uata suggests, but do the copying on your own).

like image 35
glglgl Avatar answered Oct 11 '22 00:10

glglgl


As you can not change the Employee class itself you can make a helper method which deep copies a Employee instance (you could of course also invoke the constructor directly, but I find a simple method cleaner):

public static Employee copy(Employee original){
    return new Employe(original.id, original.age, original.gender, original.fname, original.lname);
}

and with that you then can Stream the list and copy each element with a map operation:

List<Employee> employeesCopy = employees.stream() // Stream<Employee>
    .map(e -> copy(e))                            // Stream<Employee>
    .collect(Collectors.toList());                // List<Employee>
like image 3
Lino Avatar answered Oct 10 '22 22:10

Lino