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?
CodePudding user response:
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;
}
}
CodePudding user response:
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).
CodePudding user response:
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()));
CodePudding user response:
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);
CodePudding user response:
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.