Как найти дубликаты в списке?
Помогите пожалуйста с алгоритмом поиска и вывода дубликатов в списке на Java.
ArrayList<String> allUsers = new ArrayList<>(Arrays.asList("User1", "User2", "User2", "User3", "User4", "User4", "User4", "User5", "User5"));
На выходе должно получится:
{"User2", "User4", "User5"};
Если есть возможность с комментариями, что откуда берется и т.д. И будет хорошо, если получится несколько вариантов решений.
Ответы (3 шт):
Автор решения: Circassian
→ Ссылка
На котлине можно так
fun getItemsMoreOne(list: List<String>) = list
.groupBy { it }
.filter { it.value.size > 1 }
.map { it.key }
Автор решения: default locale
→ Ссылка
На английском Stack Overflow есть вопрос: Identify duplicates in a List. В ответах к нему приводится множество решений на любой вкус.
Короткий способ, через streams API:
List<String> duplicates = allUsers.stream()
//группируем в map (пользователь -> количество вхождений)
.collect(Collectors.groupingBy(Function.identity()))
//проходим по группам
.entrySet()
.stream()
//отбираем пользователей, встречающихся более одного раза
.filter(e -> e.getValue().size() > 1)
//вытаскиваем ключи
.map(Map.Entry::getKey)
//собираем в список
.collect(Collectors.toList());
Способ «вручную» через цикл и два множества:
//множество с дубликатами
final Set<String> duplicates = new HashSet<>();
//множество для отслеживания повторяющихся элементов
final Set<String> tracking = new HashSet<>();
//пробегаемся по всем пользователям
for (String user: allUsers) {
//добавляем их во множество для отслеживания
//если не получилось добавить, то значит пользователь уже встречался в списке
if (!tracking.add(user)) {
//в этом случае добавляем его во множество дубликатов
duplicates.add(user);
}
}
Вместо множества дубликатов тут можно использовать список.
Автор решения: Андрей Городецкий
→ Ссылка
Можно ещё и так:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class Duplicate {
public static void main(String[] args) {
List<String> allUsers = new ArrayList<>(Arrays.asList("User1", "User2", "User2", "User3", "User4", "User4", "User4", "User5", "User5", "User4"));
Set<String> stringSet = new HashSet<>();
Set<String> setOfDupl = allUsers.stream().filter(e -> !stringSet.add(e)).collect(Collectors.toSet());
setOfDupl.stream().forEach(System.out::println);
}
}
Неоптимально, но очень понятно, если с лямбдами знакомы конечно