[英]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.