我想在提交列表(类LegacyCommit
)中对元素进行分组,以便所有对同一用户的提交都属于自己的映射。
以下是首先获取nonDistinctCommits
Map<Boolean, List<LegacyCommit>> partitionedCommits = pushEvent.getCommits().stream()
.collect(Collectors.partitioningBy(LegacyCommit::isDistinct));
List<LegacyCommit> distinctCommits = partitionedCommits.get(true);
List<LegacyCommit> nonDistinctCommits = partitionedCommits.get(false);
现在我希望通过Map<LegacyUser, List<LegacyCommit>>
分组获得commit -> commit.getCommitter().getUsername()
,但我遇到两种情况都不起作用:
情况1
Map<LegacyUser, List<LegacyCommit>> committerGroupedNonDistinctCommits = nonDistinctCommits.stream()
.collect(Collectors.groupingBy(LegacyCommit::getCommitter));
这是关闭的,但是LegacyCommiter::getCommitter
上的地图,没有定义equals()
方法,也不想通过这种方式进行。
所以我最终使用了......
情况2
我想对用户名进行分组,同时将LegacyUser
作为键存储在地图中,我试图这样做:
Map<LegacyUser, List<LegacyCommit>> committerGroupedNonDistinctCommits = nonDistinctCommits.stream()
.collect(Collectors.groupingBy(commit -> commit.getCommitter().getUsername(), Collectors.mapping(LegacyCommit::getCommitter, Collectors.toList())));
但它无法编译,因为类型参数是错误的。
所以问题如下:
如何从Map<LegacyUser, List<LegacyCommit>>
的{{1}}分组中获取List<LegacyCommit>
?
答案 0 :(得分:3)
我认为用户名是String
(尽管任何Comparable
都可以使用此解决方案)。然后,您可以将 committer 分组到已排序的Map
中,该Map<LegacyUser, List<LegacyCommit>> committerGroupedNonDistinctCommits =
nonDistinctCommits.stream().collect(Collectors.groupingBy(
LegacyCommit::getCommitter,
()->new TreeMap<>(Comparator.comparing(LegacyUser::getUserName)),
Collectors.toList()));
按提交者的用户名排序:
Comparator
有序地图会将密钥视为相等,根据Collector
相等,组 Map
将使用提供的LegacyUser
的映射。因此,equals
没有{{1}}方法时无关紧要。
答案 1 :(得分:2)
解决此问题的一种方法是使用三步解决方案。
Map<String, List<LegacyCommit>> commitsByUsername
Map<LegacyUser, List<LegacyCommit>> results
commitsByUsername
中的列表,对于每个项目,从列表中获取第一个提交,将其用作关键字并将列表本身添加到results
我最初使用一堆流和收集器尝试了许多不同的方法,但最终总是出现编译器错误。感觉有时最简单的解决方案是最好的解决方案。
我不相信你现在可以使用典型的Java 8单行程来做到这一点。
这是一个SSCCE:
static class User {
private static int COUNTER = 0;
String username;
int notSame = COUNTER++;
@Override
public String toString() {
return String.format("{%s: %d}", username, notSame);
}
}
static class LegacyCommit {
User user;
String value;
public static LegacyCommit create(String user, String value) {
LegacyCommit commit = new LegacyCommit();
commit.user = new User();
commit.user.username = user;
commit.value = value;
return commit;
}
@Override
public String toString() {
return String.format("%s by %s", value, user);
}
}
public static void main(String[] args) {
List<LegacyCommit> commits = new ArrayList<>();
commits.add(LegacyCommit.create("a", "v1"));
commits.add(LegacyCommit.create("b", "v2"));
commits.add(LegacyCommit.create("c", "v3"));
commits.add(LegacyCommit.create("a", "v4"));
commits.add(LegacyCommit.create("b", "v5"));
commits.add(LegacyCommit.create("c", "v6"));
commits.add(LegacyCommit.create("a", "v7"));
Map<String, List<LegacyCommit>> commitsByUsername = commits.stream().collect(groupingBy(commit -> commit.user.username));
Map<User, List<LegacyCommit>> resultsss = new HashMap<>();
commitsByUsername.values().forEach(list -> resultsss.put(list.get(0).user, list));
System.out.println(resultsss);
}
答案 2 :(得分:2)
这应该这样做。首先按用户名分组,然后使用getCommiter()
作为密钥重新制作地图。
Map<LegacyUser, List<LegacyCommit>> committerGroupedNonDistinctCommits =
nonDistinctCommits.stream()
.collect(groupingBy(c -> c.getCommiter().getUsername()))
.values().stream()
.collect(toMap(lst -> lst.get(0).getCommiter(), lst->lst));