To reverse this Map, you need to iterate over its entries and for each distinct user create an entry containing a list of projects as a value in the resulting Map.
Java 8 computeIfAbsent()
This logic can be implemented using Java 8 methods Map.computeIfAbsent() and Map.forEach().
Map<String, List<User>> usersByProject = // initilizing the source map
Map<User, List<String>> projectsByUser = new HashMap<>();
usersByProject.forEach((project, users) ->
users.forEach(user -> projectsByUser.computeIfAbsent(user, k -> new ArrayList<>())
.add(project))
);
Stream API
Stream-based implementation would require a bit more effort.
The core logic remains the same. But there's one important peculiarity: we would need to generate from each entry of the source Map a sequence of new elements, containing references to a particular user and a project.
To carry this data we would need an auxiliary type, and a Java 16 record fits into this role very well. And quick and dirty alternative would be to use Map.Entry, but it's better to avoid resorting to this option because methods getKey()/getValue() are faceless, and it requires more effort to reason about the code. You can also define a regular class if you're using an earlier version of JDK.
public record UserProject(User user, String project) {}
That's how a stream-based solution might look like:
Map<String, List<User>> usersByProject = Map.of(
"projectA", List.of(new User(1, "Bob"), new User(2, "John"), new User(3, "Mo")),
"projectB", List.of(new User(2, "John"), new User(3, "Mo")),
"projectC", List.of(new User(3, "Mo"))
);
Map<User, List<String>> projectByUsers = usersByProject.entrySet().stream()
.flatMap(entry -> entry.getValue().stream().
map(user -> new UserProject(user, entry.getKey()))
)
.collect(Collectors.groupingBy(
UserProject::user,
Collectors.mapping(UserProject::project,
Collectors.toList())
));
projectsByUser.forEach((k, v) -> System.out.println(k + " -> " + v));
Output:
User[id=1, name=Bob] -> [projectA]
User[id=2, name=John] -> [projectA, projectB]
User[id=3, name=Mo] -> [projectA, projectC, projectB]