首页 > 解决方案 > 如何限制通量中的元素数量> 并将其映射到自定义结果

问题描述

假设我有说明歌曲和投票问题的课程。

用户.java

@EqualsAndHashCode
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Document(collection = "users")
public class User {

  @Id private String id;

  private String username;

  private String email;

  private Integer age;

  private String password;

  @DBRef(db = "interview", lazy = true)
  @EqualsAndHashCode.Exclude
  @ToString.Exclude
  private Set<Song> songs;
}

歌曲.java

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Song {

  @Id private String id;

  private String title;

  private String author;

  private SongGenre songGenre;

  Set<Vote> votesOfSong;
}

投票.java

@Builder
@AllArgsConstructor
@NoArgsConstructor
@Document(collection = "votes")
@Getter
public class Vote {

  @Id private String id;

  private User user;

  private Song song;

  private VoteKind voteKind;

  @Default private LocalDateTime dateOfVote = LocalDateTime.now();
}

VoteKind.java

@RequiredArgsConstructor
@Getter
public enum VoteKind {
  LIKE(1),
  DISLIKE(-1);

  private final Integer voteValue;
}

我想创建一个方法,该方法将返回最常见的SongGenreSongTitle以及特定歌曲的票数。

到目前为止,我有一个方法,例如:

public Flux<Map<Song, SongGenre>> theMostCommonSongForSongGenre(SongGenre songGenre) {
    voteRepository
        .findAll()
        .collect(
            Collectors.toMap(vote -> vote.getSong().getSongGenre(), this::getSumOfVotesForVote))
        .map(Map::entrySet)
        .flatMapMany(Flux::fromIterable)
        .filter(stringListEntry -> stringListEntry.getKey().equals(songGenre))
        .sort(Map.Entry.comparingByKey(Comparator.reverseOrder()))
        .collect(Collectors.toMap(o -> o.getKey(), o -> o.getValue()));
  }

和辅助方法:

  private int getSumOfVotesForSong(Vote vote) {
    return vote.getSong().getVotesOfSong().stream()
        .mapToInt(voteKind -> vote.getVoteKind().getVoteValue())
        .sum();
  }

这里有两个问题我无法完全解决。

  1. 如何将我的 Flux 的结果限制为例如 1 或 10 条记录。以传统方式,在 Java Stream API 中,我可以使用方法findFirstlimit但这里没有其他等效方法。我可以调用的唯一方法是limitRate,但它有另一个宿命。

  2. 如何将当前解决方案转换为 return SongGenreSongTitle以及特定歌曲的票数。是否有机会为上述参数返回 MultiMap,或者我应该使用groupingBy并返回一个自定义对象,songGenre并将songTitle其作为键和作为值 Integer,这将相当于票数。

编辑:核心 java 流解决方案可能是可取的。

对于如何实现目标的建议,我将不胜感激。

标签: javafunctional-programmingjava-streamspring-webfluxjava-11

解决方案


如果您使用的是响应式,您通常希望避免像 collect() 这样的事情,因为它是阻塞的。您可以在通量上调用 collectList() 以获取该列表的单声道。

Flux 有一个 take() 方法来限制结果。


推荐阅读