У меня есть такая логика, где я фильтрую на основе списка идентификаторов поставщиков vendors. Перед итерацией по этому потоку в коллекциях уже есть 2 элемента с тем же идентификатором поставщика, что и в списке vendors. Однако, как только список составлен, дубликаты процессов не фильтруются, и я получаю два дополнительных элемента.

Это код, как показано ниже. Что не так в filter, которое отменяет условие?

List<Vendor> nonConfiguredVendors = null;

if (entities.isEmpty()) {
    nonConfiguredVendors = vendors;
} else {
    nonConfiguredVendors = vendors.stream()
            .filter(vendor -> entities.stream()
                    .anyMatch(entity -> !vendor.getVendorId().equalsIgnoreCase(entity.getVendorId())))
            .peek(System.out::println)
            .collect(Collectors.toList());
}

Изменить : vendors имеют идентификаторы от FC_101 до FC_150. entities уже имеет FC_133 и FC_140, которые снова добавляются в список nonConfiguredVendors

0
diaop 11 Окт 2021 в 18:52

2 ответа

Лучший ответ

Ваш код недействителен:

nonConfiguredVendors = vendors.stream()
            .filter(vendor -> entities.stream()
                    .anyMatch(entity -> !vendor.getVendorId().equalsIgnoreCase(entity.getVendorId())))
            )

В вашем случае вы принимаете всех поставщиков, у которых vendorId содержится в объектах: anyMatch вернет true, если Predicate вернет true для любого T.

Таким образом, что приводит к вашей проблеме.

Правильный вариант использования (но не так):

nonConfiguredVendors = vendors.stream()
            .filter(vendor -> entities.stream()
                    .noneMatch(entity -> !vendor.getVendorId().equalsIgnoreCase(entity.getVendorId())))
            )

noneMatch вернет истину, если Predicate никогда не возвращает true или если поток пуст.

Вы должны предварительно вычислить vendorIds: вычисление его каждый раз неэффективно.

var vendorIds = entities.stream()
                        .map(e -> e.getVendorId())
                        .collect(toCollection(() -> new TreeSet<String>());

Затем отфильтруйте:

var nonConfiguredVendors = vendors.stream()
                                  .filter(vendor -> !vendorIds.contains(vendor.getVendorId()))
            .peek(System.out::println)
            .collect(Collectors.toList());
1
NoDataFound 11 Окт 2021 в 16:19

Просто создайте набор уникальных идентификаторов поставщиков в коллекции entities, а затем отфильтруйте поставщиков, используя этот набор

Set<String> uniqueIds = entities.stream()
                        .map(Entity::getVendorId)
                        .map(String::toLowerCase)
                        .collect(Collectors.toSet());

nonConfiguredVendors = vendors.stream()
                .filter(vendor -> !uniqueIds.contains(vendor.getVendorId().toLowerCase()))
                .peek(System.out::println)
                .collect(Collectors.toList());
0
mightyWOZ 11 Окт 2021 в 16:23