Сохраняйте исходный итеративный порядок сортировки стабильным, когда операции с каждым элементом дают разные результаты / длительности - PullRequest
0 голосов
/ 03 апреля 2020

Я не могу обернуть голову, как сортировки выбросов после того, как 1 выброс распакован на несколько предметов. У меня есть следующий код, пожалуйста, позвольте мне функционально объяснить.

  • Структура контента сверху вниз в базе данных A 1: n B 1: n C
  • В этой логике возврата c мы изменим вышеприведенное; A может иметь несколько B и / или C (распакованных B) непосредственно под
  • Все типы происходят от общего родителя Z, который реализует Comparable с пользовательский Comparator для переопределенного compareTo , который сортирует по уникальному возрастающему целому id по типу подкласса (поэтому он перезапускается с 0 для B и C)
  • enrichB либо возвращает один B или несколько C на основе метаданных определенного типа
  • addChildrenToA просто строитель ( .with )
private Observable<A> getChildren(final A a) {
    final Observable<List<B>> bList = containerService.getBs(a)
            .toSortedList();

    final Observable<? extends List<? extends Z>> children = bList
            .flatMapIterable(items -> items)
            .flatMap(b -> enrichB(b))
            .toList();

    return Observable.zip(
            Observable.just(A),
            children,
            this::addChildrenToA);
}

Если я уберу эту строку:

.flatMap(b -> enrichB(b))

Список children будет включать только B, поскольку разворачивание (в шаге enrichB ) никогда не происходит. Это всегда возвращает стабильный порядок сортировки в возвращенном списке:

B0, B1, B2, B3, B4

Когда Я включаю строку, один B get преобразуется в несколько C (один из элементов ). Я бы ожидал (или, может быть, sh), что это произойдет как вывод:

B0, B1, B2, C1, C2, C3, B4 (B3 распакован)

Однако .. Я получаю такие выходы, как:

B0, B1, C1, C2, C3, B2, B4

B0, C1, C2, C3, B1, B2, B4

B0, B1, B2, B4, C1, C2, C3

Таким образом, порядок "в пределах" сохраняется, но почему порядок "в целом" становится нестабильным ? Я подозреваю, что flatMap продолжит выполнять операции с enrichB и toList () -добавками и поскольку развертывание занимает больше (колеблющееся) времени, чем другие операции «вставляются» в случайные места.

  1. Верно ли мое подозрение или я что-то упускаю?
  2. Как контролировать / блокировать этот поток для поддержания стабильного порядка? Желательно без каких-либо грязных модификаций модели C включить туда id из B и изменить использованную Comparator.

1 Ответ

1 голос
/ 05 апреля 2020

Таким образом, ответом будет использование concatMap вместо flatMap.

private Observable<A> getChildren(final A a) {
final Observable<List<B>> bList = containerService.getBs(a)
        .toSortedList();

final Observable<? extends List<? extends Z>> children = bList
        .flatMapIterable(items -> items)
        .concatMap(b -> enrichB(b))
        .toList();

return Observable.zip(
        Observable.just(A),
        children,
        this::addChildrenToA);
}
...