Есть ли какой-либо способ повысить производительность приведенного ниже кода?

#java

#java

Вопрос:

Коды сравнивают 2 list кода.Первый list получен из вызова api, а второй из базы данных.Я использую 2 цикла для перебора списка и сравнения их, а также добавления общего в новый список.Первый список содержит около 800 данных, а второй список (из базы данных) содержит 150 данных.Есть ли какой-либо способ повысить производительность этого кода.Мне не разрешено вносить какие-либо изменения в AllowedCodes Class .Влияет ли использование вложенных циклов на производительность при заданном объеме данных?

 public class AllowedCodes {

    private String codeValue="";

    public String getCodeValue() {
        return codeValue;
    }

    public void setCodeValue(String codeValue) {
        this.codeValue = codeValue;
    }
}

public class CheckCodes {

    public static void main(String[] args) {

        List<AllowedCodes> old_codes_list=getListOfOldCodes();

        List<AllowedCodes> new_codes_list=new ArrayList<>();

        String sql = "This query gets the codes from database";

        PreparedStatement statement = connection.prepareStatement(sql);

        ResultSet result = statement.executeQuery();

        while(result.next()) {

            for(AllowedCodes a:old_codes){
               if(a.getCodeValue().equalsIgnoreCase(result.getCodeValue())){
                   new_codes_list.add(a);
               }
            }

        }



    }

}
  

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

1. ДА. Используйте HashSet вместо списка для old_codes_list . (Сохраняйте и сравнивайте коды в нижнем регистре, чтобы игнорировать исходный корпус.)

2. Это должен быть список массивов. Вот какой ответ я получаю от вызова api. И дубликатов нет. Есть ли какой-либо способ уменьшить временную сложность?

3. «Вот какой ответ я получаю от вызова api». скопируйте его в HashSet . Или какая-либо другая структура данных, например, Trie.

4. Копирование будет стоить вам некоторого, но затем вы можете заменить линейный for цикл на set.contains(...) , который выполняется в постоянное время (амортизированный). (Вы будете выполнять 1 линейную операцию вместо сотен.)

5. @LoneWolf: Есть много статей о том, как работает HashMap . Он включает в себя группировку элементов на основе модуля их getHashCode() значения, поэтому ему не нужно вызывать equals() каждый элемент в коллекции. Однако вам, вероятно, не нужно беспокоиться о деталях реализации, а о том, что это contains() является O(1) операцией, поэтому создание карты и проверка всех элементов становится O(n) сложной операцией вместо O(n²) .

Ответ №1:

Скопируйте список в HashMap , группируя AllowedCodes , которые имеют одинаковое значение кода в нижнем регистре:

 Map<String, List<AllowedCodes>> map =
    old_codes.stream().collect(groupingBy(a -> a.getCodeValue().toLowerCase()));
  

Затем в вашем цикле while:

 while(result.next()) {
  String resultCodeValue = result.getCodeValue().toLowerCase();
  for (AllowedCodes a : map.getOrDefault(resultCodeValue, Collections.emptyList())) {
    new_codes_list.add(a);
  }
}
  

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

1. Я попробую использовать steam api, никогда не использовал его раньше. Спасибо, Энди

2. Вы могли бы использовать stream api, чтобы полностью избежать цикла while, верно? Просто есть однострочник, который создает список после .filter(...contains(...)) ?

3. будет ли это работать с результирующим набором? Пожалуйста, предоставьте код. Я попробую его использовать. Я новичок в stream api.

4. @LoneWolf здесь используется код, показанный в вашем вопросе: » result.getCodeValue() «.

5. Да, @Andy, ваш код очень помогает. Я имел в виду StriplingWarrior , работает ли код, о котором он говорит.