Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

simplify java stream to find duplicate properties

I have a users list and I want to find all users having duplicate names:

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());

Can I improve/simplify the above solution?

For example, actually I create a list with all names and then filter it. How can I traverse the list to find its duplicate names without creating the additional list allNames?

like image 961
nimo23 Avatar asked Dec 23 '22 18:12

nimo23


2 Answers

One solution is

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());

This creates an intermediate Map<String,Boolean> to record which name is occurring more than once. You could use the keySet() of that map instead of collecting to a new 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();
            }));

A loop solution can be much simpler:

HashSet<String> seen = new HashSet<>(), duplicate = new HashSet<>();
for(User u: users)
    if(!seen.add(u.getName())) duplicate.add(u.getName());
like image 181
Holger Avatar answered Jan 08 '23 17:01

Holger


Group by the names, find entries with more than one value:

Map<String, List<User>> grouped = users.stream()
    .collect(groupingBy(User::getName));

List<User> duplicated =
    grouped.values().stream()
        .filter(v -> v.size() > 1)
        .flatMap(List::stream)
        .collect(toList());

(You can do this in a single expression if you want. I only separated the steps to make it a little more clear what is happening).

Note that this does not preserve the order of the users from the original list.

like image 40
Andy Turner Avatar answered Jan 08 '23 17:01

Andy Turner