简体   繁体   中英

Compare two different objects in different lists in Java

I need to check if an object present in list A exists in list B without using nested for loops because if the lists have a large size, it takes too much time.

This is my code :

for(Person el : persons)
{
    for(Client in : clients)
    {
        if(el.getIdentifier() == in.getTire().getIdentifier())
        {
            exists=true;
            break;
        }
    }
}

How can i achieve the same result without using loops and break?

Maybe you can do it like this

Set<String> identifierSet = new HashSet<>();

for (Person el : persons) {
    identifierSet.add(el.getIdentifier());
}

for (Client in : clients) {
    if (identifierSet.contains(in.getTire().getIdentifier())) {
        exists = true;
        break;
    }
}

You can improve performance by using data structures better suited for fast lookups. If you store clients in a HashMap where the key is the identifier, and the value is the client object then your code becomes:

for(Person el : persons)
{
    if (clients.containsKey(el.getIdentifier()) {
      exists=true;
    }
}

Now you only have one loop, and the cost of looking up in the hashmap is O(1).

This will change the complexity of your code from O(NxM) to O(N+M):

    Set<Integer> personIds = persons.stream()
            .map(e -> e.getIdentifier())
            .collect(Collectors.toCollection(HashSet::new));

    boolean exists = clients.stream().anyMatch(
            c -> personIds.contains(c.getTire().getIdentifier()));

As anyMatch is mentioned, the following solution based on Stream API can be offered (assuming the type of identifiers is String ):

// prepare set of identifiers in clients
Set<String> clientIds = clients
    .stream()                                // Stream<Client>
    .map(in -> in.getTire().getIdentifier()) // Stream<String> client ids
    .collect(Collectors.toSet());

boolean anyPersonIsClient = persons
   .stream()                    // Stream<Person>
   .map(Person::getIdentifier)  // Stream<String> person identifiers
   .anyMatch(clientIds::contains);

boolean allPersonsAreClient = persons
   .stream()                    // Stream<Person>
   .map(Person::getIdentifier)  // Stream<String> identifiers
   .allMatch(clientIds::contains);

What about a classical :

contains(Object o) //Returns true if this list contains the specified element.

So you could just do loop instead :

for(Person el : persons)
{

        if(clients.contains(el.getIdentifier()))
        {
            exists=true;
            break;
        }        
}

But looking at your code, and depending on what you're aiming for, you could use:

containsAll(Collection c)
       //   Returns true if this list contains all of the elements of the specified collection.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM