Как ограничить количество элементов во Flux > и сопоставьте это с пользовательским результатом - PullRequest
0 голосов
/ 02 марта 2020

Допустим, у меня есть классы, иллюстрирующие проблему песен и голосов, за которые проголосовали.

Пользователь. 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;
}

Я хочу создать метод, который будет возвращать наиболее распространенные SongGenre, SongTitle и количество голосов для конкретной песни.

Пока у меня есть такие методы, как:

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 я могу использовать методы findFirst или limit, но здесь нет другого эквивалентного метода. Единственный метод, который я могу вызвать - это limitRate, но у него есть другое предназначение.

  2. Как преобразовать текущее решение, чтобы получить SongGenre, SongTitle и количество голосов для конкретной песни , Есть ли шанс вернуть MultiMap для вышеуказанных параметров, или я должен использовать groupingBy и вернуть пользовательский объект с songGenre и songTitle в качестве ключа и в качестве значения Integer, которое будет эквивалентно количеству голосов.

EDIT: Core java потоковое решение может быть любым.

Буду благодарен за предложения о том, как достичь цели.

1 Ответ

1 голос
/ 11 марта 2020

Если вы используете реактив, вы обычно хотите избегать таких вещей, как collect (), поскольку он блокирует. Вы можете вызвать collectList () для потока, чтобы получить моно из этого списка.

Flux имеет метод take () для ограничения результатов.

...