如果由于某些原因您不想覆盖 equals 方法并且想要删除基于多个属性的重复项,那么我们可以创建一个通用方法来执行此操作。
我们可以写成2个版本:
1.修改原列表:
@SafeVarargs
public static <T> void removeDuplicatesFromList(List<T> list, Function<T, ?>... keyFunctions) {
Set<List<?>> set = new HashSet<>();
ListIterator<T> iter = list.listIterator();
while(iter.hasNext()) {
T element = iter.next();
List<?> functionResults = Arrays.stream(keyFunctions)
.map(function -> function.apply(element))
.collect(Collectors.toList());
if(!set.add(functionResults)) {
iter.remove();
}
}
}
2。返回一个新列表:
@SafeVarargs
public static <T> List<T> getListWithoutDuplicates(List<T> list, Function<T, ?>... keyFunctions) {
List<T> result = new ArrayList<>();
Set<List<?>> set = new HashSet<>();
for(T element : list) {
List<?> functionResults = Arrays.stream(keyFunctions)
.map(function -> function.apply(element))
.collect(Collectors.toList());
if(set.add(functionResults)) {
result.add(element);
}
}
return result;
}
在这两种情况下,我们都可以考虑任意数量的属性。
例如,根据title、author、url 和description 4 个属性删除重复项:
removeDuplicatesFromList(blogs, Blog::getTitle, Blog::getAuthor, Blog::getUrl, Blog::getDescription);
这些方法通过利用List 的equals 方法工作,该方法将检查其元素的相等性。在我们的例子中,functionResults 的元素是从传递的 getter 中检索到的值,我们可以使用该列表作为 Set 的元素来检查重复项。
完整示例:
public class Duplicates {
public static void main(String[] args) {
List<Blog> blogs = new ArrayList<>();
blogs.add(new Blog("a", "a", "a", "a"));
blogs.add(new Blog("b", "b", "b", "b"));
blogs.add(new Blog("a", "a", "a", "a")); // duplicate
blogs.add(new Blog("a", "a", "b", "b"));
blogs.add(new Blog("a", "b", "b", "b"));
blogs.add(new Blog("a", "a", "b", "b")); // duplicate
List<Blog> blogsWithoutDuplicates = getListWithoutDuplicates(blogs,
Blog::getTitle, Blog::getAuthor, Blog::getUrl, Blog::getDescription);
System.out.println(blogsWithoutDuplicates); // [a a a a, b b b b, a a b b, a b b b]
removeDuplicatesFromList(blogs,
Blog::getTitle, Blog::getAuthor, Blog::getUrl, Blog::getDescription);
System.out.println(blogs); // [a a a a, b b b b, a a b b, a b b b]
}
private static class Blog {
private String title;
private String author;
private String url;
private String description;
public Blog(String title, String author, String url, String description) {
this.title = title;
this.author = author;
this.url = url;
this.description = description;
}
public String getTitle() {
return title;
}
public String getAuthor() {
return author;
}
public String getUrl() {
return url;
}
public String getDescription() {
return description;
}
@Override
public String toString() {
return String.join(" ", title, author, url, description);
}
}
}