Как проверить отсутствие элементов в двух списках массивов различных объектов в Java? - PullRequest
2 голосов
/ 20 ноября 2019

У меня есть два класса с разными свойствами и только один с общим. Я хочу сравнить два и извлечь список с отсутствующими элементами. Так, например, у нас есть следующие классы, где inventoryId и id совпадают, и это элементы, которые мы будем искать, если они отсутствуют в списке лекарств.

public class DrugInventory {
    String inventoryId;
    String drugStatus;
}

public class Drug{
    String id;
    String name;
    String quantity;
}

inventoryID в DrugInventory равно id в Drug. Итак, вот два значения, которые я посмотрю, если они отсутствуют в списке лекарств.

List<DrugInventory> drugInventories = new ArrayList<>();

DrugInventory drugInventory = new DrugInventory("121212");
DrugInventory drugInventory1 = new DrugInventory("232323");
DrugInventory drugInventory2 = new DrugInventory("343434");
DrugInventory drugInventory3 = new DrugInventory("454545");
DrugInventory drugInventory4 = new DrugInventory("565656");

drugInventories.add(drugInventory);
drugInventories.add(drugInventory1);
drugInventories.add(drugInventory2);
drugInventories.add(drugInventory3);
drugInventories.add(drugInventory4);

List<Drug> drugs = new ArrayList<>();

Drug drug = new Drug("121212");
Drug drug1 = new Drug("232323");
Drug drug2 = new Drug("343434");

drugs.add(drug);
drugs.add(drug1);
drugs.add(drug2);

Ожидаемый результат здесь должен быть равен списку, похожему на этот:

 [DrugInventory(inventoryId=454545, drugStatus=null), DrugInventory(inventoryId=565656, drugStatus=null)]

Я могу использовать здесь вложенные циклы для сравнения каждого элемента, но это было бы неэффективно. Как я могу сделать это эффективно?

Ответы [ 3 ]

3 голосов
/ 20 ноября 2019

Для решения конкретной проблемы поиска лекарств в инвентаре, которых нет в списке лекарств, вы можете использовать:

public static List<DrugInventory> findMissingDrugs(List<Drug> drugs, 
                                                   List<DrugInventory> inventory) {
    Set<String> drugIdLookup = drugs.stream()
                                    .map(d -> d.id)
                                    .collect(Collectors.toCollection(HashSet::new));
    return inventory.stream()
                    .filter(i->!drugIdLookup.contains(i.inventoryId))
                    .collect(Collectors.toList());      
}

Сначала мы просто вытаскиваем идентификаторы в HashSet (HashSet предлагает O (1) сложность времени поиска), затем мы собираем все из инвентаря, которого нет в этом наборе поиска. Если у вас есть более сложные поиски, где вам нужно использовать несколько ключей, тогда другой ответ о реструктуризации обоих в HashMap s, где идентификаторы являются ключами, является лучшим долгосрочным подходом.

1 голос
/ 20 ноября 2019
  • Создайте Map<String, DrugInventory> и Map<String, Drug>, например, используя HashMap в качестве реализации.
  • Добавьте объекты инвентаризации лекарств и наркотиков на соответствующую карту с положением пут, используя поля id и инвентаризации каждого объекта. как первый, а объект - как второй параметр.
  • Создайте набор комбинированных значений ключей обеих карт, используя метод keySet Map.
  • Перебирайте эти ключи и извлекайте объект инвентаризации наркотиков и наркотиков изсоответствующая карта. Если оба значения не равны NULL для определенного ключа, у вас есть совпадение и вы можете распечатать интересующую вас информацию с System.out.println.
0 голосов
/ 21 ноября 2019

Я могу придумать 2 решения. Один с дополнительным пространством, а другой без дополнительного места. Это обмен между пространственной и временной сложностью, в зависимости от того, что вам больше подходит. Пример кода ниже:

1. Сортировать наркотики по двоичным файлам Поиск для каждого элемента инвентаризации наркотиков (инвентаризации).

    // Sort Drug by id
    Comparator<Drug> drugComparator = new Comparator<Drug>() {
        @Override
        public int compare(Drug d1, Drug d2) {
            return d1.id.compareTo(d2.id);
        }
    };

    Collections.sort(drugs, drugComparator);

    for (DrugInventory inventory : drugInventories) {
        if (!binarySearch(drugs, inventory.inventoryId)) {
            System.out.println(inventory.inventoryId);
        }
    }

    public static boolean binarySearch(List<Drug> drugs, String drugInventory) {

    int left = 0;
    int right = drugs.size() - 1;

    while (left <= right) {
        int middle = left + (right - left) / 2;
        int comapare = drugs.get(middle).id.compareTo(drugInventory);
        if (comapare == 0) {
            return true;
        } else if (comapare < 0) {
            left = middle + 1;
        } else {
            right = middle - 1;
        }
    }
    return false;
}

2. Используйте HashSet, добавьте и удалите элементы (id / inventoryId), остальные идентификаторы в наборе будут пропускать идентификаторы.

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

    // Add drug inventories to set
    for (DrugInventory inventoryElement : drugInventories) {
        set.add(inventoryElement.inventoryId);
    }

    // Remove drugs from set
    for (Drug drugElement : drugs) {
        set.remove(drugElement.id);
    }

    // Remaining entries in set are missing entries
    Iterator iterator = set.iterator();
    while (iterator.hasNext()) {
        System.out.println(iterator.next());
    }
...