[英]Issue with advanced java 8 stream usage
我试图使用Java 8流,以便对Message
和Member
列表执行操作。
Message
是我的域模型中的实体。 Message
具有类型为Member
的sender
字段和receiver
字段。
Member
是我的域模型中的第二个实体。 Member
具有已发送消息的集合和已接收消息的集合。
会员JPA实体 :
@Entity
public class Member implements UserDetails {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
...
@OneToMany(fetch = FetchType.LAZY, mappedBy = "sender")
private Collection<Message> sentMessages;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "recipient")
private Collection<Message> receivedMessages;
@Version
private Integer version;
消息JPA实体 :
@Entity
public class Message {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NotNull
@ManyToOne(fetch = FetchType.LAZY)
private Member sender;
@NotNull
@ManyToOne(fetch = FetchType.LAZY)
private Member recipient;
@NotNull
@Temporal(TemporalType.TIMESTAMP)
@DateTimeFormat(pattern = "dd/MM/yyyy HH:mm:ss")
private Date sendDate;
private boolean messageRead;
@NotNull
@Size(min = 5, max = 500)
@Column(length = 500)
private String text;
@Version
private Integer version;
我想从Collection<Message>
(来自给定成员的已发送和已接收消息的组合列表)中获取SortedMap<Message, Member>
,其中包含来自另一个成员的最新发送或接收消息作为键,而另一个成员为价值。
任何人都可以请教如何使用Java 8流的指针或想法,以实现此目标?
编辑1 :这是请求的示例输入/输出:
输入( message
表的内容):
#2成员的输出应该是#5和#4的消息
说明:最新的发送或涉及部件#2构件#1接收到的消息是消息#4和涉及部件#2构件#6的最新消息是消息#5。
成员#2和成员#1之间的其他消息较旧,因此未考虑在内。
最终目标是实现一个消息框,例如whatsapp / hangout或fb,通过该消息框,我可以显示当前登录的用户与其他每个用户之间最后发送或接收的消息。
如果我很好理解,这(不是单线的)是可能的实现:
SortedMap<Message, Member> sortedMap = new TreeMap<>(Comparator.comparing(Message::getSendDate).reversed());
myCombinedCollection.forEach(m -> sortedMap.put(m, m.getRecipient()));
如果您真的想要单线,则应该这样做:
SortedMap<Message, Member> sort = myCombinedCollection.stream()
.collect(Collectors.toMap(m -> m,
Message::getRecipient,
(m1, m2) -> m2,
() -> new TreeMap<>(Comparator.comparing(Message::getSendDate).reversed())));
toMap
收集器可以按以下方式分解:
Message
1->2
必须与具有2->1
映射相同)。
这是我使用的映射方法(您可能想实现自己的映射;仅用于示例):
Map<String, Optional<Message>> map = myCombinedCollection.stream()
.collect(groupingBy(Message::mapping, maxBy(Comparator.comparing(Message::getSendDate))));
完成后,将消息放入地图中,并使用下游收集器获取最新消息:
6->2 => Optional[5-Thu Apr 01 00:00:00 CEST 3915:Hi there dude]
2->1 => Optional[4-Fri Apr 02 09:45:00 CEST 3915:Je suis disponible]
结果是:
List<Message> messages = map.entrySet().stream()
.filter(e -> e.getValue().isPresent())
.map(e -> e.getValue().get())
.collect(toList());
该键在这里并不重要,因为您仅对消息感兴趣。 您可以做的是从此映射中获取List<Message>
,首先过滤为空的值:
[5-Thu Apr 01 00:00:00 CEST 3915:Hi there dude, 4-Fri Apr 02 09:45:00 CEST 3915:Je suis disponible]
最终输出:
[5-Thu Apr 01 00:00:00 CEST 3915:Hi there dude, 4-Fri Apr 02 09:45:00 CEST 3915:Je suis disponible]
如果您想看到一个小的实现,我就创建了这个小要点 。
希望能帮助到你! :)
您可以按收件人对发送的邮件进行分组,然后查找每个收件人的最新邮件(未经测试,可能有错字):
Map<Member,Message>
memberMessages =
sentMessages.stream()
.collect(Collectors.groupingBy(Message::getRecipient,
Collectors.maxBy(Comparator.comparingLong(m -> m.getSendDate().getTime())))));
这为您提供了与您想要的相反的键和值,但这应该可以帮助您入门。 例如,您可以通过创建此映射条目的Stream,然后使用toMap
收集它,在过程中反转键和值,从而创建反向映射。
我不确定整个过程是否可以在单个Stream管道中完成。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.