Как исправить проблему с сонаром squid: ForLoopCounterChangedCheck?

#java #sonarqube

#java #sonarqube

Вопрос:

Мой код был обнаружен сонаром с нарушением условий остановки цикла «for», которые должны быть неизменными. Я пытался это исправить, но сонар считает, что проблема все еще существует, потому что мой цикл for находится внутри другого цикла for.

Вот фрагмент кода:

 int limit = Const.getBatchLimit();
int count = 0;

for (int paramIndex = 0; paramIndex < paramList.size();)
{
    List<Param> tempParam = new ArrayList<>();
    StringBuilder retrieveMsg = new StringBuilder("Retrieving: n");
    for (count = 0; (count < limit) amp;amp; (paramIndex < param.size()); count  , paramIndex  )
    {
        Param myParam = paramList.get(paramIndex);
        retrieveMsg.append(myParam .seq()).append(Str.SLASH).append(Str.CRLF);
        tempParam.add(myParam);
    }
    LOGGER.info(retrieveMsg.toString());

    LOGGER.info("Done. Retrieved count: "   tempParam.size());
}
 

Я не могу переместить paramIndex до первого цикла for, потому что поведение будет отличаться от желаемого.

Буду признателен, если кто-нибудь сможет дать совет, как исправить это нарушение. Заранее благодарю вас.

Ответ №1:

Это интересный способ разбить список параметров на куски limit разного размера, но, возможно, удастся вообще избавиться от вложенного цикла.

Кроме того, если tempParam используется только для отслеживания количества элементов в пакете, его можно заменить повторным count использованием .

 int limit = Const.getBatchLimit();

StringBuilder retrieveMsg = new StringBuilder("Retrieving: n");

for (int i = 0, count = 1, n = paramList.size(); i < n; i  , count  ) {
    Param myParam = paramList.get(i);
    retrieveMsg.append(myParam.seq()).append(Str.SLASH).append(Str.CRLF);

    if (count % limit == 0 || i == n - 1) {
        LOGGER.info(retrieveMsg.toString());
        LOGGER.info("Done. Retrieved count: "   count);
        retrieveMsg = new StringBuilder("Retrieving: n");
        count = 0;
    }
}
 

Или этот код может быть полностью переработан для использования Java Stream API и реализации вспомогательного метода для обработки фрагмента (например printChunk ):

 int chunks = paramList.size() / limit   (paramList.size() % limit == 0 ? 0 : 1);
IntStream.range(0, chunks)
         .mapToObj(i -> paramList.subList(i * limit, Math.min((i   1) * limit, paramList.size()))) // getting stream of sublists
         .forEach(MyClass::printChunk);

// ...
static void printChunk(List<Param> chunk) {
    StringBuilder msg = new StringBuilder("Retrieving:n");
    chunk.forEach(p -> msg.append(p.seq()).append(Str.SLASH).append(Str.CRLF));

    LOGGER.info(msg.toString());
    LOGGER.info("Done. Retrieved count: "   chunk.size());
}

 

Комментарии:

1. спасибо за ваш ответ. попробую и сообщу, что работает.

2. попробовал ваше первое предложение, и оно сработало. еще раз спасибо.