Мне нужно проверить, существует ли объект, представленный в списке A, в списке B без использования вложенных циклов for, потому что, если списки имеют большой размер, это занимает слишком много времени.

Это мой код:

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

Как добиться того же результата без использования петель и разрывов?

1
Kapio 15 Окт 2021 в 12:19

5 ответов

Лучший ответ

Это изменит сложность вашего кода с O (NxM) на 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()));
0
Maurice Perry 15 Окт 2021 в 09:38

Может ты сможешь сделать это вот так

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;
    }
}
3
Chong Young 15 Окт 2021 в 09:34

Вы можете повысить производительность, используя структуры данных, лучше подходящие для быстрого поиска. Если вы храните клиентов в HashMap, где ключ является идентификатором, а значение - объектом клиента, тогда ваш код становится:

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

Теперь у вас есть только один цикл, а стоимость поиска в хэш-карте составляет O (1).

1
LeffeBrune 15 Окт 2021 в 09:24

Как упоминается anyMatch, может быть предложено следующее решение на основе Stream API (при условии, что тип идентификаторов 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);
1
Alex Rudenko 15 Окт 2021 в 10:03

А как насчет классики:

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

Так что вместо этого вы можете просто выполнить цикл:

for(Person el : persons)
{

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

Но глядя на свой код и в зависимости от того, к чему вы стремитесь, вы можете использовать:

containsAll(Collection c)
       //   Returns true if this list contains all of the elements of the specified collection.
0
Youri 15 Окт 2021 в 09:26