我们通常单主键查询判断,如果来了一个多个字段为主键,判断查重
public class Main {
public static void main(String[] args) {
//新增,调整为数据查询
List<StrongBuopSheetInfo> retMap = sqlService.list(dateTime);
if (CollectionUtils.isNotEmpty(retMap)) {
retMap = retMap.stream().collect(Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(
Comparator.comparing(p -> appendStrings(new String[]{ObjectUtil.toString(p.getDayId()), ";", p.getPrvnceId(), ";", p.getLatnId(), ";", p.getServiceId(), ";", p.getCallNbr()})
))), ArrayList::new));
}
}
/**
* 将字符串数组拼接在一起并返回
* StringUtil.appendStrings(new String[]{"第", String.valueOf(flag), "条,====> ", sql});
* @param strArr
* @return
*/
public static String appendStrings(String[] strArr) {
StringBuilder str2 = new StringBuilder();
if (strArr != null && strArr.length > 0) {
for (String s : strArr
) {
str2.append(s);
}
}
return str2.toString();
}
}
上面一个问题就是原本7条数据,4条重复,查重后,剩余3条,数据缺少了
如果重复4条,保留其中一条呢?java stream 多个字段重复取其中一条
在Java中,你可以使用Stream API来处理集合数据,并且你可以利用一些特性来找到并处理重复的元素。如果你有一个对象列表,并且你想基于多个字段来找到重复项,并只保留其中一条记录,你可以使用Collectors.toMap来帮助你。
下面是一个示例,假设你有一个Person类,它有两个字段:name和age,你想基于这两个字段来找到重复的人,并只保留一个。
import java.util.*;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<Person> people = Arrays.asList(
new Person("Alice", 25),
new Person("Bob", 30),
new Person("Alice", 25), // 重复项
new Person("Charlie", 35),
new Person("David", 25) // 与Alice年龄相同,但名字不同,所以不是重复项
);
Map<List<Object>, Person> uniquePersons = people.stream()
.collect(Collectors.toMap(
p -> Arrays.asList(p.getName(), p.getAge()), // 使用名字和年龄作为键
Function.identity(), // 值就是Person对象本身
(existing, replacement) -> existing // 如果键冲突(即找到重复项),保留现有的Person对象
));
// 将结果转换回列表
List<Person> result = new ArrayList<>(uniquePersons.values());
// 输出结果以验证重复项已被移除
result.forEach(person -> System.out.println(person.getName() + " " + person.getAge()));
}
}
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
在这个示例中,我们使用Collectors.toMap来创建一个Map,其中键是一个包含名字和年龄的列表,值是Person对象。如果找到具有相同名字和年龄的重复项,我们保留Map中现有的Person对象(这是由合并函数(existing, replacement) -> existing指定的)。最后,我们将Map的值转换回一个列表。
如果您正在使用PostgreSQL(通常简称为PG)并希望根据多个字段进行查重和过滤,您可以使用DISTINCT ON或GROUP BY结合HAVING子句来实现。
以下是两种方法的示例:
使用 DISTINCT ON:
假设您有一个名为 my_table 的表,并且您希望基于 field1 和 field2 进行查重,只保留每组中的第一条记录。
SELECT DISTINCT ON (field1, field2) *
FROM my_table
ORDER BY field1, field2, [some_other_field_to_determine_priority];
在这里,[some_other_field_to_determine_priority] 是用来确定在每组中哪条记录应该被保留的字段。通常,这会是一个时间戳或ID字段。
如果您想基于 field1 和 field2 进行查重,并过滤掉那些重复的记录,只留下每组中的一个代表,您可以这样做:
SELECT field1, field2, MIN(id) as representative_id
FROM my_table
GROUP BY field1, field2
HAVING COUNT(*) > 1;
这将返回所有 field1 和 field2 的组合,这些组合在表中出现的次数超过一次,并且对于每个这样的组合,它将返回具有最小 id 的记录。
根据您的具体需求,您可以选择最适合您的方法。
翻阅痕迹,方便追踪
java stream distinct() 按一个或多个指定对象字段进行去重