传递重复项的流操作
Stream operations passing on duplicates
我有这个逻辑,我根据供应商 ID 列表进行过滤 vendors
。在迭代此流之前,集合中已经有 2 个项目具有与 vendors
列表中相同的供应商 ID。但是,一旦列表被处理,重复项就不会被过滤,我会得到另外两个项目。
这是下面的代码。否定条件的 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
的 ID 从 FC_101
到 FC_150
。 entities
已经有 FC_133
和 FC_140
再次添加到 nonConfiguredVendors
列表
您的代码无效:
nonConfiguredVendors = vendors.stream()
.filter(vendor -> entities.stream()
.anyMatch(entity -> !vendor.getVendorId().equalsIgnoreCase(entity.getVendorId())))
)
在您的情况下,您将接受在实体中找到其 vendorId 的所有供应商:anyMatch
将 returns true
如果 Predicate
return s true
对于任何 T
.
因此,导致您的问题。
正确的用例(但不是)应该是:
nonConfiguredVendors = vendors.stream()
.filter(vendor -> entities.stream()
.noneMatch(entity -> !vendor.getVendorId().equalsIgnoreCase(entity.getVendorId())))
)
noneMatch
将 return 为真,如果 Predicate
从不 return true
或者流为空。
您应该预先计算 vendorId:每次计算效率不高。
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());
只需在 entities
集合中制作一组唯一的供应商 ID,然后使用该集合过滤供应商
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());
我有这个逻辑,我根据供应商 ID 列表进行过滤 vendors
。在迭代此流之前,集合中已经有 2 个项目具有与 vendors
列表中相同的供应商 ID。但是,一旦列表被处理,重复项就不会被过滤,我会得到另外两个项目。
这是下面的代码。否定条件的 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
的 ID 从 FC_101
到 FC_150
。 entities
已经有 FC_133
和 FC_140
再次添加到 nonConfiguredVendors
列表
您的代码无效:
nonConfiguredVendors = vendors.stream()
.filter(vendor -> entities.stream()
.anyMatch(entity -> !vendor.getVendorId().equalsIgnoreCase(entity.getVendorId())))
)
在您的情况下,您将接受在实体中找到其 vendorId 的所有供应商:anyMatch
将 returns true
如果 Predicate
return s true
对于任何 T
.
因此,导致您的问题。
正确的用例(但不是)应该是:
nonConfiguredVendors = vendors.stream()
.filter(vendor -> entities.stream()
.noneMatch(entity -> !vendor.getVendorId().equalsIgnoreCase(entity.getVendorId())))
)
noneMatch
将 return 为真,如果 Predicate
从不 return true
或者流为空。
您应该预先计算 vendorId:每次计算效率不高。
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());
只需在 entities
集合中制作一组唯一的供应商 ID,然后使用该集合过滤供应商
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());