在Java中,对List集合去重有多种方法,以下是一些常见的实现方式:
使用HashSet(无序去重):
1 2 3
| List<String> listWithDuplicates = ...; Set<String> set = new HashSet<>(listWithDuplicates); List<String> distinctList = new ArrayList<>(set);
|
这种方法利用了HashSet自动去除重复元素的特性。先将List转换为HashSet,然后创建一个新的ArrayList来存储不重复的元素。
使用LinkedHashSet(有序去重):
1 2 3
| List<String> listWithDuplicates = ...; LinkedHashSet<String> linkedSet = new LinkedHashSet<>(listWithDuplicates); List<String> distinctList = new ArrayList<>(linkedSet);
|
如果需要保持原顺序,可以使用LinkedHashSet,它会按照插入顺序保留元素。
使用TreeSet(排序后去重):
1 2 3
| List<String> listWithDuplicates = ...; TreeSet<String> treeSet = new TreeSet<>(listWithDuplicates); List<String> sortedDistinctList = new ArrayList<>(treeSet);
|
使用TreeSet时,除了去重外,还会根据元素的自然排序或自定义比较器进行排序。
Java 8 Stream API(有序去重):
1 2 3
| List<String> distinctList = listWithDuplicates.stream() .distinct() .collect(Collectors.toList());
|
利用Stream API的distinct()方法进行流式处理去重,最后通过collect()方法收集到新的List中。
遍历并判断添加(有序去重):
1 2 3 4 5 6 7
| List<String> listWithDuplicates = ...; List<String> distinctList = new ArrayList<>(); for (String item : listWithDuplicates) { if (!distinctList.contains(item)) { distinctList.add(item); } }
|
这种方法是逐个检查新列表中是否已包含当前元素,如果未包含则添加进去。
迭代器去重(无序去重,效率较低,不推荐):
1 2 3 4 5 6 7
| Iterator<String> iterator = listWithDuplicates.iterator(); while (iterator.hasNext()) { String current = iterator.next(); while (iterator.hasNext() && current.equals(iterator.next())) { iterator.remove(); } }
|
这种方法使用迭代器删除所有连续出现的重复项,但不保证整体上的顺序且效率较低,一般不建议使用。
每种方法都有其适用场景,根据实际需求选择合适的方法。
对象去重
在Java中,如果List集合中的元素是对象,并且想要根据对象的某个属性去重,可以使用Java 8及更高版本提供的Stream API来实现。以下是一个通用示例:
假设我们有一个用户类User,它有一个名为id的属性:
1 2 3 4 5 6 7 8
| public class User { private String id; public String getId() { return id; } }
|
现在我们有一个包含重复用户的列表,并希望根据id属性去除重复项:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| List<User> usersWithDuplicates = ...;
List<User> distinctUsersById = usersWithDuplicates.stream() .distinct() .collect(Collectors.toList());
Set<User> distinctUsersById = usersWithDuplicates.stream() .map(user -> new UserByIdWrapper(user.getId(), user)) .collect(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(UserByIdWrapper::getId))));
Set<User> setById = new TreeSet<User>((o1, o2) -> o1.getId().compareTo(o2.getId())); setById.addAll(usersWithDuplicates); List<User> listById = new ArrayList<>(setById);
List<User> distinctUsersById = usersWithDuplicates.stream() .collect(Collectors.collectingAndThen( Collectors.toMap(User::getId, Function.identity(), (u1, u2) -> u1), map -> new ArrayList<>(map.values()) ));
distinctUsersById.forEach(user -> System.out.println(user.getId()));
usersWithDuplicates.stream() .distinct() .collect(Collectors.toList());
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; return Objects.equals(id, user.id); }
@Override public int hashCode() { return Objects.hash(id); }
|
在上述代码中,若要根据id属性去重,有几种选择:
- 使用自定义包装类并结合TreeSet与Comparator的方式,当自定义Comparator时,确保其按照
id字段进行排序和比较。
- 直接修改
User类,覆盖equals()和hashCode()方法,使得两个User对象如果它们的id相同则认为是相等的。这样,在调用distinct()方法时会自动按照这个逻辑去重。
请注意,第二种方法会改变整个类的相等性判断逻辑,仅当id是决定对象唯一性的关键属性时才适合这样做。
UserByIdWrapper类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| public class User { private String id;
public static class UserByIdWrapper implements Comparable<UserByIdWrapper> { private final String id; private final User user;
public UserByIdWrapper(String id, User user) { this.id = id; this.user = user; }
public String getId() { return id; }
public User getUser() { return user; }
@Override public int compareTo(UserByIdWrapper other) { return this.id.compareTo(other.id); }
@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; UserByIdWrapper that = (UserByIdWrapper) obj; return Objects.equals(id, that.id); }
@Override public int hashCode() { return Objects.hash(id); } } }
List<User> usersWithDuplicates = ...;
Set<User> distinctUsersById = usersWithDuplicates.stream() .map(user -> new UserByIdWrapper(user.getId(), user)) .collect(Collectors.toCollection(LinkedHashSet::new));
List<User> uniqueUsers = new ArrayList<>(distinctUsersById); uniqueUsers.forEach(userWrapper -> System.out.println(userWrapper.getUser().getId()));
|