我想将元素分组到提交列表(类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())));
但它无法编译,因为类型参数是错误的。
所以问题如下:
如何从commit -> commit.getComitter().getUsername()
上的List<LegacyCommit>
分组获取Map<LegacyUser, List<LegacyCommit>>
?
我假设用户名是一个String
(尽管任何Comparable
都可以使用此解决方案(。然后,您可以按提交者分组到按提交者的用户名排序的排序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
方法时并不重要。
解决此问题的一种方法是使用三步解决方案。
- 收集
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);
}
这应该可以做到。 首先按用户名分组,然后使用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));