#java #loops
#java #циклы
Вопрос:
У меня есть этот цикл:
List<Integer> numbers = new ArrayList<Integer>();
for(int x=0; x<citiesNames.size();x ){
List<Cities> numeroCiudades = citiesRepository.findByCity(citiesNames.get(x));
numbers.add(numeroCiudades.size());
//System.out.println(numeroCiudades.size());
}
где citiesNames — это список строк, содержащий 16584 элемента, а findByCity — метод, в котором я передаю строку, и она выполняет поиск в базе данных соответствующих записей.
Что я хочу сделать, так это выполнить поиск по соответствующим записям каждого города, проверить количество записей и добавить количество записей в список целых чисел. Но этот цикл слишком медленный, для отображения результата требуется очень много времени. Как я могу это оптимизировать?
Комментарии:
1. Является ли возвращаемый тип
citiesNames.get
aString
? Возможно, оптимизация закончитсяcitiesRepository.findByCity
.2. Вы объявляете список внутри цикла. Это совсем не кажется правильным.
3. Я предполагаю, что это скорее ваш поиск в базе данных, который замедляет работу, а не добавление в ArrayList.
4. В дополнение к тому, что было сказано, может иметь смысл заранее задать емкость списка. Изменение размера большого списка (которое происходит) может привести к значительному снижению производительности. Прочитайте, что такое емкость и как работает ArrayList.
5. В дополнение к @AnisR. комментарий — попробуйте извлечь все названия городов в пакете или используя разбивку на страницы, если их количество может быть значительным (100 достаточно значительным для многих случаев использования)
Ответ №1:
Я не совсем понимаю, почему вы должны «упаковывать» все города в список, когда вы могли бы создать функцию в citiesRepository, которая возвращает значение int с количеством записей, имеющихся в этом конкретном городе. (Это значительно повысило бы производительность. Таким образом, программа могла бы просто возвращать простой int вместо создания экземпляра целого класса) (Предположим, у вас есть доступ к citiesRepository).
Кроме того, может иметь смысл заранее задать емкость списка assign. Изменение размера большого списка может привести к значительному снижению производительности (подробнее о том, как работает ArrayList, читайте здесь)
Ответ №2:
Вы могли бы использовать параллельный поток, предполагая, citiesName
что это обычный тип Java collections:
citiesName.parallelStream()
.map(citiesRepository::findByCity)
.collect(Collectors.toList())
Просто остерегайтесь подводных камней параллельного потока и того, как он использует общий ForkJoinPool
доступ.
Комментарии:
1. При этом по-прежнему извлекаются все города из базы данных. Потоки хороши для удобства чтения, а не для производительности.
2. Согласен. Пакетная операция была бы предпочтительнее, но это не всегда осуществимо (т. Е. у вас нет контроля над DAO или удаленным API, чтобы предлагать пакетную операцию). Параллельный поток — это шаг выше цикла for.
Ответ №3:
Чтобы оптимизировать этот цикл, вам придется изменить findByCity, чтобы он мог обрабатывать все это одновременно. Если вы не можете изменить findByCity, вы всегда можете использовать параллелизм с потоками:
int numbers[] = citiesNames.parallelStream()
.mapToInt(c -> citiesRepository.findByCity(c).size())
.toArray();