[英]Issue with advanced java 8 stream usage
I am trying to use java 8 streams in order to perform a manipulation on a list of Message
and Member
. 我试图使用Java 8流,以便对
Message
和Member
列表执行操作。
A Message
is a entity from my domain model. Message
是我的域模型中的实体。 A Message
has a sender
field and a receiver
field of type Member
. Message
具有类型为Member
的sender
字段和receiver
字段。
A Member
is the second entity from my domain model. Member
是我的域模型中的第二个实体。 A Member
has a collection of sent messages and a collection of received messages. Member
具有已发送消息的集合和已接收消息的集合。
Member JPA entity : 会员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;
Message JPA entity : 消息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;
From a Collection<Message>
(the combined list of sent and received messages from a given member) I want to obtain a SortedMap<Message, Member>
that contains the latest sent or received message from another member as the key and that other member as the value. 我想从
Collection<Message>
(来自给定成员的已发送和已接收消息的组合列表)中获取SortedMap<Message, Member>
,其中包含来自另一个成员的最新发送或接收消息作为键,而另一个成员为价值。
Can anyone please provice pointers or ideas on how to use java 8 streams in order to achieve this? 任何人都可以请教如何使用Java 8流的指针或想法,以实现此目标?
edit 1 : Here is a sample input/output as requested: 编辑1 :这是请求的示例输入/输出:
Input (content of message
table): 输入(
message
表的内容):
Output for member with #2 should be messages with #5 and #4 #2成员的输出应该是#5和#4的消息
Explanation: the latest sent or received messages involving member #2 with member #1 is message #4 and the latest message involving member #2 with member #6 is message #5 . 说明:最新的发送或涉及部件#2构件#1接收到的消息是消息#4和涉及部件#2构件#6的最新消息是消息#5。
Other messages between member #2 and member #1 are older so not taken into account. 成员#2和成员#1之间的其他消息较旧,因此未考虑在内。
The ultimate goal is to achieve a message box such as whatsapp/hangout or fb whereby I display the last sent or received message between the currently logged user and each of the other users. 最终目标是实现一个消息框,例如whatsapp / hangout或fb,通过该消息框,我可以显示当前登录的用户与其他每个用户之间最后发送或接收的消息。
If I understood well, this (not a one-liner), is a possible implementation: 如果我很好理解,这(不是单线的)是可能的实现:
SortedMap<Message, Member> sortedMap = new TreeMap<>(Comparator.comparing(Message::getSendDate).reversed());
myCombinedCollection.forEach(m -> sortedMap.put(m, m.getRecipient()));
If you really want a one-liner, this should do it: 如果您真的想要单线,则应该这样做:
SortedMap<Message, Member> sort = myCombinedCollection.stream()
.collect(Collectors.toMap(m -> m,
Message::getRecipient,
(m1, m2) -> m2,
() -> new TreeMap<>(Comparator.comparing(Message::getSendDate).reversed())));
The toMap
collector can be decompose as the following: toMap
收集器可以按以下方式分解:
Message
in the stream Message
1->2
has to be the same mapping has 2->1
).
1->2
必须与具有2->1
映射相同)。
This the mapping method I used (you may want to implement your own; it's just for the example): 这是我使用的映射方法(您可能想实现自己的映射;仅用于示例):
Map<String, Optional<Message>> map = myCombinedCollection.stream()
.collect(groupingBy(Message::mapping, maxBy(Comparator.comparing(Message::getSendDate))));
Once done, put the messages in the map, and use a downstream collector to get the latest message: 完成后,将消息放入地图中,并使用下游收集器获取最新消息:
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]
which results in: 结果是:
List<Message> messages = map.entrySet().stream()
.filter(e -> e.getValue().isPresent())
.map(e -> e.getValue().get())
.collect(toList());
The key is not important here since you are only interested in the messages. 该键在这里并不重要,因为您仅对消息感兴趣。 What you can do is get a
List<Message>
from this map, filtering the values that are empty first: 您可以做的是从此映射中获取
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]
Final output: 最终输出:
[5-Thu Apr 01 00:00:00 CEST 3915:Hi there dude, 4-Fri Apr 02 09:45:00 CEST 3915:Je suis disponible]
I created this small gist if you want to see a small implementation. 如果您想看到一个小的实现,我就创建了这个小要点 。
Hope it helps! 希望能帮助到你! :)
:)
You can group the sent messages by recipient and then find the latest message for each recipient (not tested, might have some typos) : 您可以按收件人对发送的邮件进行分组,然后查找每个收件人的最新邮件(未经测试,可能有错字):
Map<Member,Message>
memberMessages =
sentMessages.stream()
.collect(Collectors.groupingBy(Message::getRecipient,
Collectors.maxBy(Comparator.comparingLong(m -> m.getSendDate().getTime())))));
This gives you the key and value reversed from what you wanted, but it should get you started. 这为您提供了与您想要的相反的键和值,但这应该可以帮助您入门。 For example, you can create the reversed map by creating a Stream of this map's entries and then collecting it with
toMap
, reversing the key and value in the process. 例如,您可以通过创建此映射条目的Stream,然后使用
toMap
收集它,在过程中反转键和值,从而创建反向映射。
I'm not sure if the entire process can be done in a single Stream pipeline. 我不确定整个过程是否可以在单个Stream管道中完成。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.