3

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
David
  • 4,266
  • 8
  • 34
  • 69
  • 1
    You're looking for `person` objects in `list` whose `deptCode` does not match _any_ of the `department`s' `deptCode`s? Is that the intent of this algorithm? – jason44107 Aug 12 '21 at 15:48
  • 1
    @jason44107 ya exactly the same. I have updated the ouput in my question. Liitle efficient method will be helpful. – David Aug 12 '21 at 16:00

2 Answers2

1

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
  • 1,710
  • 13
  • 24
1

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.

  • out of curisity one quick question .. this is happening with one attribute of object. can we do the same logic for multiple attribute – David Aug 13 '21 at 04:07
  • Of course, if you wanted to check for multiple conditions you would simply add "and" or "or" to your if statement. I.e, `if(x && y){\\do something}` means "Do something if both x and y are true. `if(x || y){\\do something}` means "Do something if either of x or y, or both are true." – confusedkingbread Aug 13 '21 at 04:25
  • I have asked seperatly here. https://stackoverflow.com/questions/68766785/how-to-takeout-attribute-from-two-arralylist-of-object-which-have-different-matc – David Aug 13 '21 at 04:30
  • In terms of doing so efficiently I'm not quite sure, I'd have to spend some time thinking about it. I have not studied time complexity enough for these things to come to me naturally. I will check it out and perhaps answer later. – confusedkingbread Aug 13 '21 at 04:33
  • Actually I wanted to avoid two loops here. thats it. I am also looking forsome key based solution. thanks – David Aug 13 '21 at 04:35
  • 1
    You want to check each element of list a in regards to the data of list b - that is impossible without two loops. The algorithm can be changed to not use nested loops (like explained), but we cannot get rid of the two loops – roookeee Aug 13 '21 at 10:29