Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find elements in a list that are not present in another list using java 8

I have 2 lists. The requirement is to filter out elements in list1 that are not in list2 based on condition.

  Class Fighter
  {
    String name;
    String address;
  }     
  List<Fighter> pairs1 = new ArrayList();
    pairs1.add(new Fighter("a", "a"));
    pairs1.add(new Fighter("b", "a"));

    List<Fighter> pairs2 = new ArrayList();
    pairs2.add(new Fighter("a", "c"));
    pairs2.add(new Fighter("a", "d"));
    Set<Fighter> finalValues = new HashSet<>();


    finalValues = pairs1.stream().filter(firstList -> 
   pairs2.stream().noneMatch(secondList -> 
   firstList.getName().equals(secondList.getName())
            && firstList.getName().equals(secondList.getName()))).collect(Collectors.toSet());

    System.out.println(finalValues);

Expected Output : a=a, b=a

Explanation: Elements in list1 that are not in list2

The above code is not giving the expected output. Please let me know how the above stream code can be corrected to get the output

like image 997
shreya Avatar asked Aug 23 '19 07:08

shreya


People also ask

How do you check if an element of a list is in another list Java?

contains() in Java. ArrayList contains() method in Java is used for checking if the specified element exists in the given list or not. Returns: It returns true if the specified element is found in the list else it returns false.

How do you check if a value is present in a list in Java 8?

We can check whether an element exists in ArrayList in java in two ways: Using contains() method. Using indexOf() method.

How do you check if two ArrayList has the same element?

You can compare two array lists using the equals() method of the ArrayList class, this method accepts a list object as a parameter, compares it with the current object, in case of the match it returns true and if not it returns false.


2 Answers

First override the equals and hashcode methods in Fighter class.

@Override
public boolean equals(Object o) {
    if (o == this)
        return true;
    if (!(o instanceof Fighter))
        return false;
    Fighter f = (Fighter) o;
    return f.name.equals(name) && f.address.equals(address);
}

@Override
public int hashCode() {
    int result = name.hashCode();
    result = 31 * result + address.hashCode();
    return result;
}

Then create a Set from pairs2. Finally use it's contains method to get the set difference. Here's how it looks,

Set<Fighter> pairs2Set = new HashSet<>(pairs2);
Set<Fighter> setDiff = pairs1.stream()
    .filter(f -> !pairs2Set.contains(f))
    .collect(Collectors.toSet());
like image 93
Ravindra Ranwala Avatar answered Nov 07 '22 20:11

Ravindra Ranwala


You do not use address when matching inside the filter.

List<Fighter> res = pairs1.stream()
                    .filter(f -> !pairs2.stream()
                                        .anyMatch(s -> f.getName().equals(s.getName())
                                                  && f.getAddress().equals(s.getAddress())))
                   .collect(Collectors.toList());

Here filter the element of first list if contains in second list based on condition.

Better approach:

Using List's contains method

List<Fighter> res = pairs1.stream()
                            .filter(e -> !pairs2.contains(e)) 
                            .collect(Collectors.toList());

You need to override equals() method in Fighter class. contains() method you will use the equals() method to evaluate if two objects are the same.

@Override
public boolean equals(Object o) {
    if (o == this)
        return true;
    if (!(o instanceof Fighter))
        return false;
    Fighter f = (Fighter) o;
    return f.name.equals(name) && f.address.equals(address);
}

But using Set it will be more faster. See similar problem solution using Set

like image 3
Eklavya Avatar answered Nov 07 '22 21:11

Eklavya