从 Java 8 中基于多个属性的对象列表中删除重复项

我想比较 getCode & getMode 并找到重复的记录。


然后还有一个产品属性 getVode,它在两条记录中始终具有不同的值(真或假)。


P1   getCode  getMode  getVode

1    001      123      true

P2   getCode  getMode  getVode

2    001      123      false

我在下面尝试过,但它只找到重复项:


List<ProductModel> uniqueProducts = productsList.stream()

    .collect(Collectors.collectingAndThen(

        toCollection(() -> new TreeSet<>(

            Comparator.comparing(ProductModel::getCode)

                .thenComparing(ProductModel::getMode)

        )),

        ArrayList::new));

因此,当我找到重复记录时,我想检查 getVode 值为 false 并将其从列表中删除。任何帮助,将不胜感激?


郎朗坤
浏览 161回答 4
4回答

MMMHUHU

据我了解,只有当元素重复并且它们的getVode方法返回时,您才想删除元素false。我们可以从字面上做到这一点。首先,我们必须确定哪些元素是重复的:Map<Object,&nbsp;Boolean>&nbsp;isDuplicate&nbsp;=&nbsp;productsList.stream() &nbsp;&nbsp;&nbsp;&nbsp;.collect(Collectors.toMap(pm&nbsp;->&nbsp;Arrays.asList(pm.getCode(),&nbsp;pm.getMode()), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pm&nbsp;->&nbsp;false,&nbsp;(a,&nbsp;b)&nbsp;->&nbsp;true));然后,删除那些满足条件的:productsList.removeIf(pm&nbsp;->&nbsp;!pm.getVode() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&&&nbsp;isDuplicate.get(Arrays.asList(pm.getCode(),&nbsp;pm.getMode())));或者,不修改旧列表:List<ProductModel>&nbsp;uniqueProducts&nbsp;=&nbsp;new&nbsp;ArrayList<>(productsList); uniqueProducts.removeIf(pm&nbsp;->&nbsp;!pm.getVode() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&&&nbsp;isDuplicate.get(Arrays.asList(pm.getCode(),&nbsp;pm.getMode())));这也可以通过 Stream 操作来完成:List<ProductModel>&nbsp;uniqueProducts&nbsp;=&nbsp;productsList.stream() &nbsp;&nbsp;&nbsp;&nbsp;.filter(pm&nbsp;->&nbsp;pm.getVode() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;||&nbsp;!isDuplicate.get(Arrays.asList(pm.getCode(),&nbsp;pm.getMode()))) &nbsp;&nbsp;&nbsp;&nbsp;.collect(Collectors.toList());

qq_遁去的一_1

在这里,无论值是什么,您都删除了重复项getVode(),因为在传递Comparator给TreeSet.你的方法不容易。您可以根据可以用类表示的元素和值对元素进行分组来创建。 然后对于 Map 进程的每个条目:如果列表包含单个元素,则保留它,否则不要保留所有这些必须为false 的元素。 Map<ProductModelId, List<ProductModelId>>getCode()getMode()ProductModelIdgetVode()Map<ProductModelId, List<ProductModel>> map =&nbsp;productsList.stream()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .collect(groupingBy(p -> new ProductModelId(p.getCode(), p.getMode());List<ProductModel> listFiltered =&nbsp; &nbsp; &nbsp; &nbsp; map.values()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.stream()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.flatMap(l -> {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (l.size() == 1) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return Stream.of(l.get(0));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return l.stream().filter(ProductModel::getVode);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.collect(toList());请注意,ProductModelId应该equals/hashCode通过考虑两个字段的值来覆盖它们以在地图中正确地对它们进行分组:public class ProductModelId {&nbsp; &nbsp; private String code;&nbsp; &nbsp; private String mode;&nbsp; &nbsp; public ProductModelId(String code, String mode) {&nbsp; &nbsp; &nbsp; &nbsp; this.code = code;&nbsp; &nbsp; &nbsp; &nbsp; this.mode = mode;&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public boolean equals(Object o) {&nbsp; &nbsp; &nbsp; &nbsp; if (this == o) return true;&nbsp; &nbsp; &nbsp; &nbsp; if (!(o instanceof ProductModelId)) return false;&nbsp; &nbsp; &nbsp; &nbsp; ProductModelId that = (ProductModelId) o;&nbsp; &nbsp; &nbsp; &nbsp; return Objects.equals(code, that.code) &&&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Objects.equals(mode, that.mode);&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public int hashCode() {&nbsp; &nbsp; &nbsp; &nbsp; return Objects.hash(code, mode);&nbsp; &nbsp; }}

慕尼黑8549860

如果您vode可以用于true多个实例ProductModel(否则,如果您期望一个实例true- 这更简单,我会让这个练习给您)并且您想要保留所有实例,这可能就是您想要的:&nbsp; &nbsp; List<ProductModel> models = List.of(&nbsp; &nbsp; &nbsp; &nbsp; new ProductModel(1, 123, false),&nbsp; &nbsp; &nbsp; &nbsp; new ProductModel(1, 123, true)); // just an example&nbsp; &nbsp; Map<List<Integer>, List<ProductModel>> map = new HashMap<>();&nbsp; &nbsp; models.forEach(x -> {&nbsp; &nbsp; &nbsp; &nbsp; map.computeIfPresent(Arrays.asList(x.getMode(), x.getCode()),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(key, value) -> {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;value.add(x);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;value.removeIf(xx -> !xx.isVode());&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return value;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;});&nbsp; &nbsp; &nbsp; &nbsp; map.computeIfAbsent(Arrays.asList(x.getMode(), x.getCode()),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; key -> {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; List<ProductModel> list = new ArrayList<>();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; list.add(x);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return list;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; });&nbsp; &nbsp; map.values()&nbsp; &nbsp; &nbsp; &nbsp;.stream()&nbsp; &nbsp; &nbsp; &nbsp;.flatMap(List::stream)&nbsp; &nbsp; &nbsp; &nbsp;.forEachOrdered(x -> System.out.println(x.getCode() + "&nbsp; " + x.getMode()));哪里ProductModel是这样的:&nbsp; &nbsp; static class ProductModel {&nbsp; &nbsp; private final int code;&nbsp; &nbsp; private final int mode;&nbsp; &nbsp; private final boolean vode;&nbsp; &nbsp; // some other fields, getters, setters}这不是那么容易实现的。您首先需要查找是否存在重复项,并且只有在找到重复项时才采取相应措施。map.computeIfAbsent注意放入地图键(aKey由Code/Mode包裹在Arrays::asList- 它正确覆盖hashCode/equals)。当基于该 Key 找到重复项时,我们希望通过map.computeIfPresent. “表演”也不是微不足道的,考虑到它vode可以true跨越多个实例(是的,这是我的假设)。你不知道vode之前的钥匙在这张地图上放了什么——是吗false?如果是这样,它必须被删除。但是电流false也是吗?如果是这样,它也必须被删除。

慕少森

您可以按代码和模式的组合进行分组。然后在 mergeFunction 中获取带有truevode 的元素:&nbsp;Collection<ProductModel>&nbsp;uniqueProducts&nbsp;&nbsp;=&nbsp;products.stream() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.collect(toMap( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;->&nbsp;Arrays.asList(p.getCode(),&nbsp;p.getMode()), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Function.identity(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(p1,&nbsp;p2)&nbsp;->&nbsp;p1.getVode()&nbsp;?&nbsp;p1&nbsp;:&nbsp;p2)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.values();请参阅javaDoc 了解 toMap
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java