2015-03-02 58 views
0

我有以下的JPA實體:問題與Java 8流的數據採集接口

@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; 

從消息的集合(Collection<Message> messages)我想通過無論是在收件人或發件人字段分組獲得Map<Member, List<Message>> messageMap

爲了進一步定義我的用例,連接的成員(currentMember)有一些發送和接收的消息附加到它的實例。我想要檢索與消息添加到將包含所有連接構件的消息(發送或接收)的集合如下:

Collection<Message> messages = new ArrayList<Message>(); 
messages.addAll(currentMember.getSentMessages()); 
messages.addAll(currentMember.getReceivedMessages()); 

和用於與該當前成員已在交換彼此/相對構件至少一條消息,我想獲得所有交換消息的列表。

然後我就可以構建上面的Map<Member, List<Message>> messageMap

這是可能的開箱即用的API或我需要實現我自己的收藏家嗎?

回答

2

如果我正確理解你的問題,你希望統一使用接收者作爲發送消息的關鍵字並使用發送者作爲接收消息的關鍵字來處理消息。您可以通過在收集操作使用條件做到這一點:

Map<Member, List<Message>> map = Stream.concat(
    currentMember.getSentMessages().stream(), currentMember.getReceivedMessages().stream()) 
.collect(Collectors.groupingBy(msg -> 
        msg.getSender()==currentMember? msg.getRecipient(): msg.getSender())); 

它會使用,發送者或接收者,爲關鍵取決於與該currentMember比較的結果,所以,關鍵將永遠是「另一邊」。它可能不是最有效的解決方案,因爲它評估事先已知的信息,但它很簡單。

如果您希望避免重新生成已知信息,則必須通過信息流將其攜帶。在沒有標準Pair型的你可以使用Map.Entry實例來封裝對「所需的關鍵」和Message實例:

Map<Member, List<Message>> map = 
    Stream.concat(
     currentMember.getSentMessages().stream().map(msg -> 
      new AbstractMap.SimpleImmutableEntry<>(msg.getRecipient(), msg)), 
     currentMember.getReceivedMessages().stream().map(msg -> 
      new AbstractMap.SimpleImmutableEntry<>(msg.getSender(), msg))) 
    .collect(Collectors.groupingBy(e -> e.getKey(), 
       Collectors.mapping(e->e.getValue(), Collectors.toList()))); 

在這裏,不僅包裝入對的代碼,收集操作的代碼複雜化也由於所需的解包而變得更加複雜。

決定哪個方向去取決於你...