Поток, используя компаратор сбрасывая значения - PullRequest
0 голосов
/ 19 ноября 2018

Я начинающий разработчик с небольшим опытом использования потоков Java.Я определил (с помощью дополнительной регистрации), что следующий поток удаляет запись, которую я специально ищу, но я не могу понять, почему.Обратите внимание, я не написал этот код, и человек, который сделал это, покинул компанию.В этом проекте используется Spring.

Таблица ConfirmCode структурирована следующим образом:

  Name              Type    Length  Not Null
  confirm_code_id   int     11      True
  account_id        varchar 20      False
  product_id        varchar 20      False
  dimension         varchar 55      False
  confirm_code      int     1       False
  confirm_desc      varchar 50      False
  action_enum       enum    0       False 
  sms_keywords      varchar 255     False 

В этой таблице содержатся конкретные перечисления с пустыми значениями для account_id, product_id и измерения по типу:

  ConfirmCode
  accountId productId dimension code desc               enum     keywords
                                  2  Need to Reschedule RESCHED  {not important}
                                  7  Call Transferred   TRANSFER {not important}
                                 -1  Help               HELP     {not important}
                                 -2  Opt In             OPT IN   {not important}
                                 -3  Opt Out            OPT OUT  {not important}
                                 -4  Response           RESPONSE {not important}    
                                  1  Confirmed          CONFIRM  {not important}

Однако клиент (accountID) может переопределить код, связанный с перечислением по умолчанию.Например:

  ConfirmCode
  accountId productId dimension             code desc               enum     keywords
  704442    RemindMe  Appointment Reminder  2    Confirmed          CONFIRM  {not important}    

Поскольку accountId, productId и dimension могут иметь значение NULL, запрос, выполняемый Spring, должен это учитывать, а также клиент, переопределяющий значения по умолчанию, как вы можете видеть выше (parentв этом случае учетная запись является нулевой).

Query:
public interface ConfirmCodeRepository extends JpaRepository<ConfirmCode, Long> {

  @Query("SELECT c FROM ConfirmCode c WHERE (accountId is null OR accountId = :parentAccountId OR accountId = :accountId) "
        + " AND (productId = :productId OR productId is NULL)"
        + " AND (dimension is null OR dimension = :dimension)")

  public List<ConfirmCode> findByAccountIdAndProductIdAndDimension(
        @Param("accountId") String accountId, @Param("parentAccountId") String parentAccountId,
        @Param("productId") String productId, @Param("dimension") String dimension);

Проблема, с которой я сталкиваюсь, заключается в том, что при запросе таблицы ConfirmCode для клиента 704442 эта запись возвращается для этого клиента, но позже удаляется после прохождения через Comparatorкод в потоке.Только записи, где accountId, productId и dimension имеют значение null.Вот код, который выполняет логику для набора результатов из запроса:

@Repository
public class ConfirmCodeDAO {

    @Autowired
    ConfirmCodeRepository confirmCodeRepo;
    private static final Logger logger = LoggerFactory.getLogger(PreferenceService.class);

    public Set<ConfirmCode> findByAccountIdAndParentAccountIdAndProductIdAndDimension(
            String accountId,
            String parentAccountId, String productId, String dimension) {

        List<ConfirmCode> list = confirmCodeRepo
                .findByAccountIdAndProductIdAndDimension(accountId, parentAccountId, productId,
                        dimension);
        list.forEach(r -> logger.info("list: " + r.toString()));

        Set<ConfirmCode> set = confirmCodeRepo
                .findByAccountIdAndProductIdAndDimension(accountId, parentAccountId, productId,
                        dimension)
                .stream()
                .sorted(Comparator.comparing(ConfirmCode::getActionEnum,
                        Comparator.nullsFirst(Comparator.naturalOrder())))
                .sorted(Comparator.comparing(ConfirmCode::getDimension,
                        Comparator.nullsFirst(Comparator.naturalOrder())))
                .sorted(Comparator.comparing(ConfirmCode::getProductId,
                        Comparator.nullsFirst(Comparator.naturalOrder())))
                .sorted(Comparator.comparing(ConfirmCode::getAccountId,
                        Comparator.nullsFirst(Comparator.reverseOrder())))
                .collect(Collectors.toMap(ConfirmCode::getConfirmCode, confirmCode -> confirmCode,
                        (c1, c2) -> c2))
                .entrySet()
                .stream()
                .map(e -> e.getValue())
                .collect(Collectors.toSet());
        set.forEach(r -> logger.info("set2: " + r.toString()));
        return set;
    }
}

Вот логирование для объекта «список»:

Calling confirmCodeDAO with: 704442, parentAccountId: null, productId: RemindMe, dimension: Appointment Reminder
list: [accountId=704442, productId=RemindMe, dimension=Appointment Reminder, confirmCode=2, confirmDesc=Confirmed, actionEnum=CONFIRM, smsKeywords={not important}]
list: [accountId=null, productId=null, dimension=null, confirmCode=1, confirmDesc=Confirmed, actionEnum=CONFIRM, smsKeywords={not important}]
list: [accountId=null, productId=null, dimension=null, confirmCode=2, confirmDesc=Need to Reschedule, actionEnum=RESCHED, smsKeywords={not important}]
list: [accountId=null, productId=null, dimension=null, confirmCode=7, confirmDesc=Call Transferred, actionEnum=TRANSFER, smsKeywords={not important}, account=null, responseType=null]
list: [accountId=null, productId=null, dimension=null, confirmCode=3, confirmDesc=Repeat, actionEnum=REPEAT, smsKeywords={not important}, account=null, responseType=null]
list: [accountId=null, productId=null, dimension=null, confirmCode=-1, confirmDesc=Help, actionEnum=HELP, smsKeywords={not important}, account=null, responseType=null]
list: [accountId=null, productId=null, dimension=null, confirmCode=-2, confirmDesc=Opt In, actionEnum=OPT IN, smsKeywords={not important}, account=null, responseType=null]
list: [accountId=null, productId=null, dimension=null, confirmCode=-3, confirmDesc=Opt Out, actionEnum=OPT OUT, smsKeywords={not important}, account=null, responseType=null]
list: [accountId=null, productId=null, dimension=null, confirmCode=-4, confirmDesc=Response, actionEnum=RESPONSE, smsKeywords={not important}, account=null, responseType=null]
list: [accountId=null, productId=null, dimension=null, confirmCode=-5, confirmDesc=Cancelled, actionEnum=CANCEL, smsKeywords={not important}, account=null, responseType=null]

Вот логированиедля объекта "set":

set: [accountId=null, productId=null, dimension=null, confirmCode=-1, confirmDesc=Help, actionEnum=HELP, smsKeywords={not important}]
set: [accountId=null, productId=null, dimension=null, confirmCode=1, confirmDesc=Confirmed, actionEnum=CONFIRM, smsKeywords={not important}]
set: [accountId=null, productId=null, dimension=null, confirmCode=-5, confirmDesc=Cancelled, actionEnum=CANCEL, smsKeywords={not important}]
set: [accountId=null, productId=null, dimension=null, confirmCode=7, confirmDesc=Call Transferred, actionEnum=TRANSFER, smsKeywords={not important}]
set: [accountId=null, productId=null, dimension=null, confirmCode=3, confirmDesc=Repeat, actionEnum=REPEAT, smsKeywords={not important}, account=null, responseType=null]
set: [accountId=null, productId=null, dimension=null, confirmCode=-2, confirmDesc=Opt In, actionEnum=OPT IN, smsKeywords={not important}, account=null, responseType=null]
set: [accountId=null, productId=null, dimension=null, confirmCode=-4, confirmDesc=Response, actionEnum=RESPONSE, smsKeywords={not important}, account=null, responseType=null]
set: [accountId=null, productId=null, dimension=null, confirmCode=-3, confirmDesc=Opt Out, actionEnum=OPT OUT, smsKeywords={not important}, account=null, responseType=null]

Вы видите, что после прохождения потокового кода нужная мне запись отбрасывается.Пожалуйста, сообщите об этом и спасибо за ваше время!

1 Ответ

0 голосов
/ 19 ноября 2018

Сама отсортированная не может отбрасывать элементы. Но, собирая список, используя

toMap.collect(Collectors.toMap(ConfirmCode::getConfirmCode, confirmCode -> 
confirmCode, (c1, c2) -> c2))

у вас есть только один для каждого свойства verifyCode.

Этот сборщик карт работает следующим образом:

Первый параметр определяет ключ, поэтому он принимает в качестве ключа свойство verifyCode объекта ConfigmCode (имена немного вводят в заблуждение). Вторым является значение confirmCode -> confirmCode, поэтому весь объект сохраняется как значение. Следовательно мы получаем Map<Integer, ConfirmCode>.

Третий параметр описывает, как объединить два значения, если на карте уже есть ключ. Функции (c1,c2) -> c2 просто говорят: возьмите вторую.

В вашем списке первый и третий элементы оба имеют verifyCode = 2, поэтому на карте остается только второй элемент.

Как обсуждено в комментариях, это только удаляет второй элемент (в списке ввода) с verifyItem = 2 из-за компараторов, которые сортируют нуль сначала.

Карта теперь содержит ожидаемые элементы, но когда значения собираются в набор, метод equals из ConfirmCode определяет объекты, которые будут равны, если они имеют одинаковый actionEnum. В то время как первый элемент (который отсортирован до конца) имеет тот же actionEnum, что и второй элемент в списке, сборщик сохраняет только первый элемент.

...