How to compare to Arraylist of object based on key in efficient way

Viewed 76

How to compare to Arraylist of object based on key in efficient way.

I have an array of object personDetails and departmentDetails.

Here I am trying to find the difference between the two object based on the attribute called deptCode.

Here is what I am trying.

package com.education;

import java.util.*;
import java.util.stream.Collectors;

public class educationMain {

    public static void main(String[] args) {
        
        List<person> list=new ArrayList<person>();  
        person l1 = new person(1,"Samual",100,"Sales","Business");
        person l2 = new person(2,"Alex",100,"Sales","Business");
        person l3 = new person(3,"Bob",101,"Engineering","Technology");
        person l4 = new person(4,"Michel",101,"Engineering","Technology");
        person l5 = new person(5,"Ryan",102,"PR","Services");
        person l6 = new person(6,"Horward",103,"Leadership","Managmnet");
        person l7 = new person(7,"Cyna",104,"HR","Human Resource");
        list.add(l1);  
        list.add(l2);  
        list.add(l3); 
        list.add(l4);  
        list.add(l5);  
        list.add(l6); 
        list.add(l7); 
        
        
        
         List<department> depList = new ArrayList<department>();
         
         
         department d1 = new department(100, "Sales","Business");
         department d2 = new department(101, "Engineering","Technology");
         department d3 = new department(102, "PR","Services");
         depList.add(d1);  
         depList.add(d2);  
         depList.add(d3); 

         List<person> listC = new ArrayList<person>();
         
         
         for(person p : list) {
             boolean  flag = false;
             for (department d:depList) {
                 if(p.deptCode == d.deptCode) {
                     flag = false;
                     break;
                 }else {
                     flag = true;
                 }
             }
             if(flag == true) {
                 listC.add(p);
             }
         }
         
         for(person b:listC){  
             System.out.println(b.personId+" "+b.name+" "+b.deptCode+" "+b.parentDept+" "+b.deptName); 
         }
    }

}

Now this printing what eatly i want. But I am using two for loop. Can anyone help me to optimize my code because I am using two loop here. I want to try the code which filter out the delta based on some.

In Collection I saw set will do but not able to write that. Canone helpme to optimise the efiiciency.

Output :

6 Horward 103 Leadership Managmnet

 7 Cyna 104 HR Human Resource
2 Answers

Given a list of persons of the size p and a list of departments of the size d your current algorithm has a complexity of O(p * d).

You could iterate the departments once and add their department codes into a HashSet<Integer> and check that set for every persons deparatment code - complexity: O(d + p). This is computationally more efficient while requiring more memory - the classic time vs. memory trade-off:

List<Person> persons = ...;
List<Department> departments = ...

Set<Integer> existingDepartmentIds = new HashSet<>();
for (Department d : departments) {
    existingDepartmentIds.add(d.deptCode); 
}

List<Person> personsWithMatchingDepartmentId = new ArrayList<>();
for (Person p : persons) {
   if (existingDepartmentIds.contains(p.deptCode)) {
       personsWithMatchingDepartmentId.add(p);
   }
}

I wrote this in an imperative style as I don't know if you are proficient with Stream etc. A functional variant would look like this:

List<Person> persons = ...;
List<Department> departments = ...

Set<Integer> existingDepartmentIds = departments.stream()
   .map(Department::getDeptCode)
   .collect(Collectors.toSet());


List<Person> personsWithMatchingDepartmentId = persons.stream()
    .filter(p -> existingDepartmentIds.contains(p.deptCode))
    .collect(Collectors.toList());

roookeee already gave a great answer. My approach is about the same, here's my implementation:

After adding all of your departments to the list, iterate over the departments, adding the codes to a HashSet. I'm not sure exactly what the class methods are, however, assuming they follow JavaBean conventions, it will probably look something like this:

//Create an instance of HashSet
HashSet<Integer> codeSet = new HashSet<>();

//Iterate over the departments and add the department code to a set.
depList.forEach(dept->{
    codeSet.add(dept.getDeptCode());
  });


List<person> listC = new ArrayList<>();

list.forEach(p->{
    if(!codeSet.contains(p.getDeptCode())){
    listC.add(p);
    }
  });

/**
 *This reads logically as, "For each person, if the set of department codes 
 *DOES NOT contain this persons department code, add them to the list".
 */

Please excuse any poor code formatting, I haven't spoken Java in a while as I've been trying to learn Python. Also, I have no professional experience programming, I'm just some teenager who thinks coding is kind of neat, so, don't take my word as gospel.

Related