nimo23:
Eu tenho uma users
lista e eu quero encontrar todos os usuários com nomes duplicados:
var allNames = users
.stream()
.map(u -> u.getName()).collect(Collectors.toList());
var duplicateNames = allNames
.stream()
.filter(i -> Collections.frequency(allNames, i) > 1)
.collect(Collectors.toSet());
Posso melhorar / simplificar a solução acima?
Por exemplo, na verdade eu criar uma lista com todos os nomes e depois filtrá-la. Como posso percorrer a lista para encontrar seus nomes duplicados sem criar a lista adicional allNames
?
Holger:
Uma solução é
var duplicate = users.stream()
.collect(Collectors.toMap(User::getName, u -> false, (x,y) -> true))
.entrySet().stream()
.filter(Map.Entry::getValue)
.map(Map.Entry::getKey)
.collect(Collectors.toSet());
Isto cria um intermediário Map<String,Boolean>
de ficha que nome está a ocorrer mais do que uma vez. Você pode usar o keySet()
de que o mapa em vez de recolher para um novo Set
:
var duplicate = users.stream()
.collect(Collectors.collectingAndThen(
Collectors.toMap(User::getName, u -> false, (x,y) -> true, HashMap::new),
m -> {
m.values().removeIf(dup -> !dup);
return m.keySet();
}));
Uma solução loop pode ser muito mais simples:
HashSet<String> seen = new HashSet<>(), duplicate = new HashSet<>();
for(User u: users)
if(!seen.add(u.getName())) duplicate.add(u.getName());