public class Member {
private String name;
private String team;
private List<String> tasks;
...
}
输入列表如:
member1, team1, [task1]
member2, team1, [task2]
member2, team1, [taks3]
member3, team2, [task4]
member3, team2, [task5, task6]
尝试按团队分组并将每个成员的任务聚合在一起,如何编写流?预期结果为Map<String, List<Member>>
,如:
team1: [
member1: [task1]
member2: [task2, task3]
]
team2: [
member3: [task4, task5, task6]
]
按团队分组很容易。挑战在于如何聚合每个不同成员的任务,并仍将结果保持为“Map&gt;
”更新:这是我能做的最好的,但这是两步。任何人都可以合并这些吗?
public class Test {
public static void main(String[] args) {
Member m1 = new Member("member1", "team1", task("task1"));
Member m2 = new Member("member2", "team1", task("task2"));
Member m3 = new Member("member2", "team1", task("task3"));
Member m4 = new Member("member3", "team2", task("task4"));
Member m5 = new Member("member3", "team2", task("task5"));
List<Member> list = Arrays.asList(m1, m2, m3, m4, m5);
long start = System.currentTimeMillis();
Map<String, Map<String, Optional<Member>>> result = list.stream()
.collect(Collectors.groupingBy(Member::getTeam,
Collectors.groupingBy(Member::getName, Collectors.reducing(
(member1, member2) -> {
member1.getTasks().addAll(member2.getTasks());
return member1;
}
))));
Map<String, List<Member>> result2 = result.entrySet().stream()
.collect(Collectors.toMap(entry -> entry.getKey(),
entry -> entry.getValue().values().stream()
.map(e -> e.get()).collect(Collectors.toList())));
result2.entrySet().stream().forEach(System.out::println);
long end = System.currentTimeMillis();
System.out.println("Total:" + (end - start) + "ms");
}
private static List<String> task(String... tasks) {
List<String> list = new ArrayList<>();
Collections.addAll(list, tasks);
return list;
}
}
答案 0 :(得分:1)
您的任务包括两个步骤:按团队分组,然后按成员分组并合并他们的任务。
试试这个:
Map<String, List<Member>> result =
members.stream()
.collect(groupingBy(Member::getTeam,
collectingAndThen(groupingBy(Member::getName,
reducing(null, (m1, m2) -> {
if (m1 == null) {
return m2;
}
List<String> tasks = new ArrayList<>();
tasks.addAll(m1.getTasks());
tasks.addAll(m2.getTasks());
m2.setTasks(tasks);
return m2;
})), map -> new ArrayList<>(map.values()))));
答案 1 :(得分:1)
以下收藏家组合应该做到这一点。
我确信这是技术上可行的一个很好的例子,但在可读性方面却不是一个好主意。
List<Member> list = ...
Map<String, Map<String, List<String>>> map = list.stream()
.collect(Collectors.groupingBy(Member::getTeam,
Collectors.groupingBy(Member::getName,
Collectors.mapping(Member::getTasks,
Collectors.collectingAndThen(Collectors.toList(),
(doubleList) -> doubleList.stream()
.flatMap(lst -> lst.stream())
.collect(Collectors.toList()))))));
使用以下输入(添加构造函数)进行测试时:
List<Member> list = Arrays.asList(
new Member("name1", "team1", Arrays.asList("task1", "task11")),
new Member("name1", "team1", Arrays.asList("task2", "task22")),
new Member("name1", "team2", Arrays.asList("task1", "task11")));
生成的地图包含:
{team1={name1=[task1, task11, task2, task22]}, team2={name1=[task1, task11]}}
答案 2 :(得分:0)
这可以使用scrollRangeToVisible
函数来实现。
在你的例子中:
let rect = ayatTextView.layoutManager.boundingRect(forGlyphRange: viewRange, in: ayatTextView.textContainer)
ayatTextView.contentOffset = CGPoint(x: 0, y: rect.origin.y)