Multiple NULL addition into a List in Java

1.8k Views Asked by At

I have 2 lists and want to copy some element from one to another, i.e. there are old and new employees list I need to union 2 lists and delete the elements that include to the old list but not include in the new one.

I could solve the part of getting the union and intersection by using TreeSet and override the equals and hashcode functions of the Employees class....

Now, I want to exclude the elements that are in the old but not in the new and add them to the "deletedList"....which I got "ConcurrentModificationException"

I tried this instead of "iterator" but the same result: for(Employees e : employeesListDB)

Also I tried "CopyOnWriteArrayList" instead of "ArrayList" but no change!!

but the problem now that at the initialization of the empty list "deletedList" it is filled with multiple null elements before the add function!

Here is the code:

List<Employees> employeesListDB = this.findAll();     

Set<Employees> empSet = new TreeSet<Employees>(new EmployeeComparator());
empSet.addAll(employeesList);

List<Employees> deletedList = new ArrayList<Employees>();
Employees e = new Employees();

ListIterator<Employees> itr = employeesListDB.listIterator();    
for(itr.hasNext()) { 
  e = (Employees)itr.next();
  if(!empSet.contains(e)) {
    deletedList.add(e);
  }               
}

A counter Example:

The oldlist "employeesListDB" the employees list from the database:

[  
    {  
        "email":"[email protected]"
    },
    {  
        "email":"[email protected]"
    },
    {  
        "email":"[email protected]"
    },
    {  
        "email":"[email protected]"
    },
    {  
        "email":"[email protected]"
    },
    {  
        "email":"[email protected]"
    }
]

The new list to be added:

[  
    {  
        "email":"[email protected]"
    },
    {  
        "email":"[email protected]"
    },
    {  
        "email":"[email protected]"
    }  

]

The deleted list that I want:

[
{
"email":"[email protected]" }, {
"email":"[email protected]" }, {
"email":"[email protected]" }, {
"email":"[email protected]" }, {
"email":"[email protected]" } ]

Sara mail will be updated...

Employee class has two fields {id,email} the new list (the list to be added to the db) is a list of only emails, id field are not recognized yet but the old list has the complete bean fields ...to compare between these 2 list I should override the Comparator to ignore the id field; Finding duplicates in a List ignoring a field

JUST I need to know, why when I use set.add operation, it adds the unique emails only! the original size of the list was 36 elements after adding it into a set it becomes only 16!!

 Set<Employees> oldSet = new TreeSet<Employees>(new EmployeeComparator());
        oldSet.addAll(employeesListDB);

        Set<Employees> newSet = new TreeSet<Employees>(new EmployeeComparator());
        newSet.addAll(employeesList);


        Set<Employees> deleted = Sets.difference(oldSet, newSet);
5

There are 5 best solutions below

1
On BEST ANSWER

Try it this way (Made a small TestCase):

private static Employee createEmployee(String string) {
    Employee employee = new Employee();
    employee.setEmail(string);
    return employee;
}

public static void main(String[] args)  {

    List<String> newMails = new ArrayList<>();
    List<Employee> oldList = new ArrayList<>();

    oldList.add(createEmployee("[email protected]"));
    oldList.add(createEmployee("[email protected]"));
    oldList.add(createEmployee("[email protected]"));
    oldList.add(createEmployee("[email protected]"));
    oldList.add(createEmployee("[email protected]"));
    oldList.add(createEmployee("[email protected]"));

    newMails.add("[email protected]");
    newMails.add("[email protected]");
    newMails.add("[email protected]");

    List<Employee> delete = new ArrayList<>();
    Set<String> removedMails = new HashSet<>();

    for (Employee emp : oldList) {
        if (!newMails.contains(emp.getEmail())) {
            delete.add(emp);
        }
        removedMails.add(emp.getEmail());
    }
    newMails.removeAll(removedMails);
    // remove emploeyees in delete
    oldList.removeAll(delete);

    // Create employee for left MAils
    for (String newMail : newMails) {
        oldList.add(createEmployee(newMail));
    }

    //Old and new Employees
    for (Employee emp : oldList) {
        System.out.println(emp.getEmail());
    }

}

simple Employee class:

class Employee {
String email;

public String getEmail() {
    return email;
}

public void setEmail(String email) {
    this.email = email;
}

}

output:

[email protected]
[email protected]
[email protected]
3
On

Here is a core Java solution using 2 simple steps:

[1] - Create a set setOld which contains the first set of emails
[2] - Subtract from setOld a new set of emails setNew

Set oldSet<String> = new HashSet<String>();  // original set of email addresses
oldSet.add("[email protected]");
oldSet.add("[email protected]");
oldSet.add("[email protected]");
oldSet.add("[email protected]");
oldSet.add("[email protected]");
oldSet.add("[email protected]");

Set newSet<String> = new HashSet<String>();  // new set of email addresses
newSet.add("[email protected]");
newSet.add("[email protected]");
newSet.add("[email protected]");

for (String s : newSet) {
    oldSet.remove(s);     // this will only remove the element if found
}

// display new contents of oldSet
for (String s : oldSet) {
    System.out.println(s);
}

Output:

[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
0
On

Use List removeAll method. You will need to override equals method in your Employees class. PFB sample snippet based on employee id, you will need to modify it to fit based on email id:

import java.util.*;

public class StringArray {

    public static void main(String args[]) {

        List<Employee> oldList = new ArrayList<Employee>();
        oldList.add(new Employee(1));
        oldList.add(new Employee(2));
        oldList.add(new Employee(3));
        oldList.add(new Employee(4));

        List<Employee> newList = new ArrayList<Employee>();
        newList.add(new Employee(3));
        newList.add(new Employee(4));
        newList.add(new Employee(5));
        newList.add(new Employee(6));

        oldList.removeAll(newList);

        System.out.println("Printing delete list");
        for (Employee employee : oldList)
            System.out.println(employee);

        System.out.println("Printing updated list");
        for (Employee employee : newList)
            System.out.println(employee);
    }
}

public class Employee {
    private int id; 

    public Employee(int id) {
        super();
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "Employee [id=" + this.id + "]";
    }

    @Override
    public boolean equals(Object o) {       

        if (o == this)
            return true;        

        if (!(o instanceof Employee)) 
            return false; 

        Employee c = (Employee) o;         

        return this.id == c.id;     
    }   
}
3
On

the empty list filled with multiple null elements before the add function!

This is becuase you're using the ArrayList which contains the following constant:

private static final int DEFAULT_CAPACITY = 10;

Which mean when you create the ArrayList<T> with the new operator you actually create an Array of T which contains 10 nulls (It's contained as private transient Object[] elementData field).

The JLS said:

Every variable in a program must have a value before its value is used:

Each class variable, instance variable, or array component is initialized with a default value when it is created (§15.9, §15.10.2):

[...]

For all reference types (§4.3), the default value is null.

9
On

As I understand, you need all elements that are contained by old set and not contained by new set.

For this purpose you can use Guava Sets#difference method:

Set<Employees> deleted = Sets.difference(oldSet, newSet);

Test with your data:

Set<String> oldEmployees = Sets.newHashSet("[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]");
Set<String> newEmployees = Sets.newHashSet("[email protected]", "[email protected]", "[email protected]");

Set<String> diff = Sets.difference(oldEmployees, newEmployees);

System.out.println(diff);

Result:

[[email protected], [email protected], [email protected], [email protected], [email protected]]