使用Java Streams获取嵌套在HashMap中的大多数元素的集合

Bra*_* B. 9 java hashmap set java-8 java-stream

所以情况就是这样:我需要在某些日期登记人们的投票.简而言之,提出了一个日期,人们投票支持他们想要的日期.

数据结构如下:

private HashMap<LocalDateTime, Set<Vote>> votes;
Run Code Online (Sandbox Code Playgroud)

投票是:

public class Vote {
    private String name;
    private VoteType vote;

    public Vote(String name, VoteType vote) {
        super();
        this.name = name;
        this.vote = vote;
    }
}
Run Code Online (Sandbox Code Playgroud)

其中VoteType只是一个枚举:

public enum VoteType {YES, NO, MAYBE}
Run Code Online (Sandbox Code Playgroud)

现在我已经创建了一个返回可用性投票数量的流(VoteType):

public Map<LocalDateTime, Integer> voteCount(VoteType targetVote) {
    return this.votes.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> new Integer(
            e.getValue().stream().filter(v -> v.getVote() == targetVote).collect(Collectors.toList()).size())));
}
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:如何使用Java Streams获得最多"YES"的日期.

/* Returns the date that got the most 'YES' votes */
public LocalDateTime winningDate() {
    // TODO
}
Run Code Online (Sandbox Code Playgroud)

感谢您的帮助!

Ous*_* D. 6

所以我的问题是:如何使用Java Streams获得最多"YES"的日期.

这将是一个漫长的...

  1. 我们需要到达一个我们拥有的位置,Stream<LocalDateTime>以便我们可以稍后按日期分组应用counting下游收集器以获得该特定日期的投票数量,我们可以通过这个结构来完成此结构flatMap.
  2. 我们只需要保留投票类型所在的对象 YES
  3. 我们按日期对结果进行分组,并将值作为该YES特定日期的投票数.
  4. 我们流过entrySetmax通过投票找到日期

码:

/* Returns the date that got the most 'YES' votes */
public Optional<LocalDateTime> getWinningDate() {
    return votes.entrySet() // Set<Entry<LocaleDateTime, Set<Vote>>
            .stream() // Stream<Entry<LocaleDateTime, Set<Vote>>
            .flatMap(e -> e.getValue().stream().filter(a -> a.getVote() == VoteType.YES)
                         .map(x -> e.getKey())) // Stream<LocalDateTime>
           .collect(groupingBy(Function.identity(), counting())) // Map<LocaleDateTime, Long>
           .entrySet() // Set<Entry<LocaleDateTime, Long>>
           .stream() // Stream<Entry<LocaleDateTime, Long>>
           .max(Comparator.comparingLong(Map.Entry::getValue)) // Optional<Entry<LocaleDateTime, Long>>
           .map(Map.Entry::getKey); // Optional<LocalDateTime>
}
Run Code Online (Sandbox Code Playgroud)
  • 请注意,我已经将方法返回类型更改为 Optional<LocaleDateTime>,我本可以返回, .map(Map.Entry::getKey).orElse(null)因此您可以维护当前的方法返回类型,LocalDateTime但这只是感觉很糟糕,所以我决定推迟决定做什么客户的"无价值案例".
  • 我已将方法名称更改getWinningDate为增强可读性.

至于处理Optional<T>,在你的情况下,如果你想nullgetWinningDate返回一个空的Optional 的情况下有一个值,你可以安全地打开它:

LocalDateTime winningDate = getWinningDate().orElse(null);
Run Code Online (Sandbox Code Playgroud)

或者如果您想提供默认日期:

LocalDateTime winningDate = getWinningDate().orElse(defaultDate);
Run Code Online (Sandbox Code Playgroud)

或者,如果您确定总会有结果,那么只需致电get().

LocalDateTime winningDate = getWinningDate().get();
Run Code Online (Sandbox Code Playgroud)

等等..