3

My question is - How to remove objects from the list by comparing it with the second list.

List1 - The first list contains email addresses.
List2 - The second list contains only domains in the format "@domain.com" etc

I would like to remove objects (e-mails) from the first list that contain domains from the second list.

For example:
If List1 contain email address: "email@domain.com" and second List2 contain "@domain.com" - then I want to remove this email (from List1)

I tried to use:

List1.removeIf(s -> s.equals (List2));
List1.removeAll(List2);

Unfortunately, it does not filter my list as I would like.

I will be grateful for your quick help

  • 1
    The **String** "someone@domain.com" can't possibly be equal to a **List** of domains. They're not even of the same type. You need to learn more about basic stuff like what equality means. What you want to do is to extract the domain from the email address (i.e. transform the string "someone@domain.com" into the string "domain.com", and then check if the list of domains **contains** the result (i.e. contains "domain.com"). – JB Nizet Oct 15 '18 at 12:54

3 Answers3

5

Something like

list1.removeIf(email -> list2.stream().anyMatch(email::endsWith));

should work

OhleC
  • 2,821
  • 16
  • 29
3

First, create a HashSet with your domains:

Set<String> domains = new HashSet<>(list2);

Now, use removeIf in the first list:

list1.removeIf(email -> domains.contains("@" + email.split("@")[1]));

The idea to use a Set (instead of the original list2) is to optimize the search, i.e. to make contains run in O(1) amortized time.

Note: I'm assuming all domains in list2 start with "@".

fps
  • 33,623
  • 8
  • 55
  • 110
  • 2
    Since domain names are case-insensitive, while your lists may contain mixed case, you might want to ensure all domains in list2 are in lowercase, and then do `domains.contains("@" + email.split("@")[1].toLowerCase())`. – DodgyCodeException Oct 16 '18 at 14:58
  • 2
    Also, split uses regular expressions which can often use a lot of CPU time. A more efficient way might be `domains.contains(email.substring(email.indexOf('@').toLowerCase()))`. – DodgyCodeException Oct 16 '18 at 15:03
1

You can create a new list of objects to be removed from first list and after delete them:

List<String> objectsToBeRemoved = list1.stream()
                                        .filer(email-> isNotValidEmail(email,list2))
                                        .collect(toList());
list1.removeAll(objectsToBeRemoved);

Another option is to use removeIf:

    List<String> emails = new ArrayList<>(Arrays.asList("email@domain.com", "email2@domain.com","ssss@ff.com"));
    List<String> domains = new ArrayList<>(Arrays.asList("@domain.com"));
    emails.removeIf(email -> isNotValidEmail(domains, email));

private boolean isNotValidEmail(List<String> domains, String email) {
    return domains.stream()
            .anyMatch(email::endsWith);
}
Adina Rolea
  • 2,031
  • 1
  • 7
  • 16