Search code examples
javalistjava-streamset-difference

Comparing two list values and finding only values from one list that do not exist in another


I have two list as shown below

List<Test> fisrtList= Arrays.asList(
                new Test(1, 1L),
                new Test(2, 3L),
                new Test(2, 4L)
                
                );
        
List<Long> secondList=Arrays.asList(3L, 5L);
//Find value of second  list that are not in first list

Expected answer from the comparision should be 5L as it is not in firstList.

Here is my Test class

public class Test {
    
    public Test(int id, Long idNo) {
        this.id=id;
        this.idNo=idNo;
    }

    private int id;
    
    private Long idNo;

    public int getId() {
        return id;
    }

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

    public Long getIdNo() {
        return idNo;
    }

    public void setIdNo(Long idNo) {
        this.idNo = idNo;
    }
    
}

How can I find the Long values from secondList that are not in the firstList?


Solution

  • If you want to use streams for this purpose the most efficient approach will look like this:

        public static List<Long> removeIntersection(List<Long> source, List<Test> valuesToRemove) {
            Set<Long> toRemove = toSet(valuesToRemove);
            return source.stream()
                    .filter(num -> !toRemove.contains(num))
                    .collect(Collectors.toList());
        }
    
        private static Set<Long> toSet(List<Test> valuesToRemove) {
            return valuesToRemove.stream()
                    .map(Test::getIdNo)
                    .collect(Collectors.toSet());
        }
    

    The same result could be achieved by utilizing removeAll() and retainAll() methods from the Collection interface. These methods are optimized for ArrayList and perform in a linear time.

    You just have to coerce your list of test objects to a list of Long and make a copy of the second list which gonna be mutated.

    To demonstrate how these methods work let's consider the following example with lists of Integer values.

    removeAll() will remove all elements contained in the given collection from this collection

    retainAll() will retain only elements contained in both collections

        public static void main(String[] args) {
            List<Integer> source = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6, 7, 8, 9));
            List<Integer> valuesToRemove = new ArrayList<>(List.of(1, 2, 3, 4));
            source.removeAll(valuesToRemove);
            System.out.println("result of removeAll: " + source);
    
            source = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6, 7, 8, 9));
            List<Integer> valuesToRetain = new ArrayList<>(List.of(5, 6, 7, 8, 9));
            source.retainAll(valuesToRetain);
            System.out.println("result of retainAll: " + source);
        }
    

    output

    result of removeAll: [5, 6, 7, 8, 9]
    result of retainAll: [5, 6, 7, 8, 9]