按列表中的多个枚举值对对象列表进行分组
Group a list of objects by multiple enum values in a list
上下文:
我有一个 Topic
枚举:
public enum Topic {
RELATIONSHIP, DATING, EDUCATION, FITNESS, NEWS, RENT, EVENTS, GIVEAWAY, SALE
}
和一个 class 成员,其字段是主题列表。一名成员至少有一个,最多 9 个主题,he/she 已订阅。
@AllArgsConstructor
@Getter
@ToString
static class Member {
String id;
List<Topic> topics;
String email;
}
我每周收到一次消息列表。每条消息都属于一种主题类型。消息列表不包含具有相同主题的消息(没有重复的主题且从不为空,1 到 9 个条目)
@AllArgsConstructor
@Getter
@ToString
static class Message {
String id;
Topic topic;
String content;
}
问题:
给定一个消息列表和一个成员列表,创建一个映射 Map<Message, List<Member>>
用于向每个成员发送通知。每个成员应该只收到 he/she 已订阅的主题的通知。
我的做法:
- 从消息列表创建一个
Map<Topic, Message>
(如您在下面的示例中看到的那样完成)
- 从成员列表创建
Map<Topic, List<Member>>
。 (我被困在这里,不知道如何从成员主题列表中提取单个主题来创建我想要的地图)
- 在我得到上面的两个映射后创建一个最终映射
<Message, List<Member>>
将第一个映射的值映射到第二个映射的相应值。应该很简单。
示例设置:
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;
public class Example {
public static void main(String[] args) {
List<Message> messages = List.of(new Message("KW41",Topic.EDUCATION,"Some educational content published"),
new Message("KW41",Topic.FITNESS,"Some fitness content published"),
new Message("KW41",Topic.DATING,"Some dating content published"),
new Message("KW41",Topic.RENT,"Some rent content published"));
List<Member> memberList = List.of(new Member("1", List.of(Topic.SALE, Topic.RENT), "john@gmail.com"),
new Member("2", List.of(Topic.DATING, Topic.NEWS), "jess@gmail.com"),
new Member("3", List.of(Topic.EDUCATION), "jane@gmail.com"),
new Member("4", List.of(Topic.FITNESS, Topic.RENT, Topic.EDUCATION), "jojo@gmail.com"),
new Member("5", List.of(Topic.RELATIONSHIP), "jina@gmail.com"),
new Member("6", List.of(Topic.SALE, Topic.NEWS), "jimi@gmail.com"),
new Member("7", List.of(Topic.NEWS, Topic.EVENTS), "jd@gmail.com"));
Map<Topic,Message> messageMap = messages.stream().collect(Collectors.toMap(Message::getTopic, Function.identity()));
messageMap.entrySet().forEach(System.out::println);
}
@AllArgsConstructor
@Getter
@ToString
static class Member {
String id;
List<Topic> topics;
String email;
}
@AllArgsConstructor
@Getter
@ToString
static class Message {
String id;
Topic topic;
String content;
}
enum Topic {
RELATIONSHIP, DATING, EDUCATION, FITNESS, NEWS, RENT, EVENTS, GIVEAWAY, SALE
}
}
如何从成员列表中获得按主题分组的 Map<Topic, List<Member>>
。 (我不能轻易做到 stream.collect(Collectors.groupingBy(Member::getTopics))
因为它是一个列表。我需要先以某种方式提取它们)。所需的地图应包含(仅添加成员 ID 以提高可读性)
Topic.RELATIONSHIP=[5]
Topic.DATING=[2]
Topic.EDUCATION=[3, 4]
Topic.FITNESS=[4]
Topic.NEWS=[2, 6, 7]
Topic.RENT=[1, 4]
Topic.EVENTS=[7]
Topic.SALE=[1, 6]
展平成元组可能会有所帮助。
例如:
@Value
class Tuple<L, R> {
L left;
R right;
}
你可以:
Stream<Member> stream = ...;
Map<Topic, List<Member>> result = stream
.flatMap(member -> member.getTopics().stream().map(topic -> new Tuple<>(topic, member)))
.collect(groupingBy(Tuple::getLeft, mapping(Tuple::getRight, toList())));
上下文:
我有一个 Topic
枚举:
public enum Topic {
RELATIONSHIP, DATING, EDUCATION, FITNESS, NEWS, RENT, EVENTS, GIVEAWAY, SALE
}
和一个 class 成员,其字段是主题列表。一名成员至少有一个,最多 9 个主题,he/she 已订阅。
@AllArgsConstructor
@Getter
@ToString
static class Member {
String id;
List<Topic> topics;
String email;
}
我每周收到一次消息列表。每条消息都属于一种主题类型。消息列表不包含具有相同主题的消息(没有重复的主题且从不为空,1 到 9 个条目)
@AllArgsConstructor
@Getter
@ToString
static class Message {
String id;
Topic topic;
String content;
}
问题:
给定一个消息列表和一个成员列表,创建一个映射 Map<Message, List<Member>>
用于向每个成员发送通知。每个成员应该只收到 he/she 已订阅的主题的通知。
我的做法:
- 从消息列表创建一个
Map<Topic, Message>
(如您在下面的示例中看到的那样完成) - 从成员列表创建
Map<Topic, List<Member>>
。 (我被困在这里,不知道如何从成员主题列表中提取单个主题来创建我想要的地图) - 在我得到上面的两个映射后创建一个最终映射
<Message, List<Member>>
将第一个映射的值映射到第二个映射的相应值。应该很简单。
示例设置:
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;
public class Example {
public static void main(String[] args) {
List<Message> messages = List.of(new Message("KW41",Topic.EDUCATION,"Some educational content published"),
new Message("KW41",Topic.FITNESS,"Some fitness content published"),
new Message("KW41",Topic.DATING,"Some dating content published"),
new Message("KW41",Topic.RENT,"Some rent content published"));
List<Member> memberList = List.of(new Member("1", List.of(Topic.SALE, Topic.RENT), "john@gmail.com"),
new Member("2", List.of(Topic.DATING, Topic.NEWS), "jess@gmail.com"),
new Member("3", List.of(Topic.EDUCATION), "jane@gmail.com"),
new Member("4", List.of(Topic.FITNESS, Topic.RENT, Topic.EDUCATION), "jojo@gmail.com"),
new Member("5", List.of(Topic.RELATIONSHIP), "jina@gmail.com"),
new Member("6", List.of(Topic.SALE, Topic.NEWS), "jimi@gmail.com"),
new Member("7", List.of(Topic.NEWS, Topic.EVENTS), "jd@gmail.com"));
Map<Topic,Message> messageMap = messages.stream().collect(Collectors.toMap(Message::getTopic, Function.identity()));
messageMap.entrySet().forEach(System.out::println);
}
@AllArgsConstructor
@Getter
@ToString
static class Member {
String id;
List<Topic> topics;
String email;
}
@AllArgsConstructor
@Getter
@ToString
static class Message {
String id;
Topic topic;
String content;
}
enum Topic {
RELATIONSHIP, DATING, EDUCATION, FITNESS, NEWS, RENT, EVENTS, GIVEAWAY, SALE
}
}
如何从成员列表中获得按主题分组的 Map<Topic, List<Member>>
。 (我不能轻易做到 stream.collect(Collectors.groupingBy(Member::getTopics))
因为它是一个列表。我需要先以某种方式提取它们)。所需的地图应包含(仅添加成员 ID 以提高可读性)
Topic.RELATIONSHIP=[5]
Topic.DATING=[2]
Topic.EDUCATION=[3, 4]
Topic.FITNESS=[4]
Topic.NEWS=[2, 6, 7]
Topic.RENT=[1, 4]
Topic.EVENTS=[7]
Topic.SALE=[1, 6]
展平成元组可能会有所帮助。
例如:
@Value
class Tuple<L, R> {
L left;
R right;
}
你可以:
Stream<Member> stream = ...;
Map<Topic, List<Member>> result = stream
.flatMap(member -> member.getTopics().stream().map(topic -> new Tuple<>(topic, member)))
.collect(groupingBy(Tuple::getLeft, mapping(Tuple::getRight, toList())));