我想比较 getCode 和 getMode 并找到重复的记录。
然后还有一个产品属性 getVode,它在两条记录中始终具有不同的值(true 或 false)。
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 并将其从列表中删除。 任何帮助将不胜感激?
据我了解,只有当元素是重复的并且它们的getVode
方法返回
false
时,你才想删除它们。我们可以从字面上做到这一点。首先,我们必须确定哪些元素是重复的:
Map<Object, Boolean> isDuplicate = productsList.stream()
.collect(Collectors.toMap(pm -> Arrays.asList(pm.getCode(), pm.getMode()),
pm -> false, (a, b) -> true));
然后,删除满足条件的:
productsList.removeIf(pm -> !pm.getVode()
&& isDuplicate.get(Arrays.asList(pm.getCode(), pm.getMode())));
或者,不修改旧列表:
List<ProductModel> uniqueProducts = new ArrayList<>(productsList);
uniqueProducts.removeIf(pm -> !pm.getVode()
&& isDuplicate.get(Arrays.asList(pm.getCode(), pm.getMode())));
也可以通过Stream操作来完成:
List<ProductModel> uniqueProducts = productsList.stream()
.filter(pm -> pm.getVode()
|| !isDuplicate.get(Arrays.asList(pm.getCode(), pm.getMode())))
.collect(Collectors.toList());
getVode()
值是多少,因为传递给
Comparator
的
TreeSet
中不考虑它。你的方法并不容易。
Map<ProductModelId, List<ProductModelId>>
类表示的
getCode()
和
getMode()
值对元素进行分组来创建
ProductModelId
。然后对于 Map 的每个条目进行处理:如果列表包含单个元素,则保留它,否则不要保留所有
getVode()
为 false 的元素。
Map<ProductModelId, List<ProductModel>> map =
productsList.stream()
.collect(groupingBy(p -> new ProductModelId(p.getCode(), p.getMode());
List<ProductModel> listFiltered =
map.values()
.stream()
.flatMap(l -> {
if (l.size() == 1) {
return Stream.of(l.get(0));
} else {
return l.stream().filter(ProductModel::getVode);
}
}
)
.collect(toList());
请注意,
ProductModelId
应通过考虑两个字段的值来覆盖
equals/hashCode
,以便在地图中将它们正确分组:
public class ProductModelId {
private String code;
private String mode;
public ProductModelId(String code, String mode) {
this.code = code;
this.mode = mode;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ProductModelId)) return false;
ProductModelId that = (ProductModelId) o;
return Objects.equals(code, that.code) &&
Objects.equals(mode, that.mode);
}
@Override
public int hashCode() {
return Objects.hash(code, mode);
}
}
vode
可以是
true
的多个
ProductModel
实例(否则,如果您期望单个
true
- 这更简单,我将让这个练习给您)并且您想保留它们所有,也许这就是您所追求的:
List<ProductModel> models = List.of(
new ProductModel(1, 123, false),
new ProductModel(1, 123, true)); // just an example
Map<List<Integer>, List<ProductModel>> map = new HashMap<>();
models.forEach(x -> {
map.computeIfPresent(Arrays.asList(x.getMode(), x.getCode()),
(key, value) -> {
value.add(x);
value.removeIf(xx -> !xx.isVode());
return value;
});
map.computeIfAbsent(Arrays.asList(x.getMode(), x.getCode()),
key -> {
List<ProductModel> list = new ArrayList<>();
list.add(x);
return list;
});
});
map.values()
.stream()
.flatMap(List::stream)
.forEachOrdered(x -> System.out.println(x.getCode() + " " + x.getMode()));
其中
ProductModel
类似于:
static class ProductModel {
private final int code;
private final int mode;
private final boolean vode;
// some other fields, getters, setters
}
这并不是那么容易实现的。您首先需要查找是否存在重复项,只有在发现重复项时才采取相应措施。
map.computeIfAbsent
小心地放入地图键(
Key
是由
Code/Mode
包裹在
Arrays::asList
中制成的 - 它正确地覆盖了
hashCode/equals
)。当根据该密钥找到重复项时,我们希望通过
map.computeIfPresent
采取行动。考虑到
vode
可以在多个实例中成为
true
(是的,这是我的假设),“表演”也不是微不足道的。您不知道之前的钥匙在这张地图中放入了什么
vode
- 是
false
吗?如果是这样,则必须将其删除。但现在的
false
也是吗?如果是这样,也必须将其删除。
Map uniqueList = new HashMap();
for (Map elem : elemList) {
String key = (String) elem .get("xx") + (String) elem .get("yy") + (String) elem .get("zz");
uniqueList.put(key, service);
}
return new ArrayList<Map>(uniqueList.values());