簡體   English   中英

Java 8流高級用法的問題

[英]Issue with advanced java 8 stream usage

我試圖使用Java 8流,以便對MessageMember列表執行操作。

Message是我的域模型中的實體。 Message具有類型為Membersender字段和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
  • 構造一個新條目,將消息作為關鍵字,並將接收者成員作為值
  • 您將其放置在TreeMap中,該MapMap將消息作為發送日期進行比較
  • 如果兩條消息的發送日期相同,則僅保留一條


自進行編輯以來,映射實際上更加復雜,因為實際上您必須考慮消息的發送日期以及發送者和接收者之間的映射。 因此,您必須創建一個返回唯一映射的函數(警告:您需要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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM