Отложено от этого Как применить сортировку и ограничение после группы, используя Java потоков , потому что я хочу решить эту проблему ровно за одну итерацию
Представьте себе У меня есть следующая сущность:
public static class Hospital {
private AREA area;
private int patients;
public Hospital(AREA area, int patients) {
this.area = area;
this.patients = patients;
}
public AREA getArea() {
return area;
}
public void setArea(AREA area) {
this.area = area;
}
public int getPatients() {
return patients;
}
public void setPatients(int patients) {
this.patients = patients;
}
}
public enum AREA {
AREA1,
AREA2,
AREA3
}
Теперь, учитывая список больниц, я хочу найти районы с большинством пациентов в них, вот что я сделал до сих пор:
public static void main(String[] args) {
List<Hospital> list = Arrays.asList(
new Hospital(AREA.AREA1, 20),
new Hospital(AREA.AREA2, 10),
new Hospital(AREA.AREA1, 10),
new Hospital(AREA.AREA3, 40),
new Hospital(AREA.AREA2, 10));
Map<AREA, Integer> map = findTopTen(list);
for (AREA area : map.keySet())
System.out.println(area);
}
public static Map<AREA, Integer> findTopTen(Iterable<Hospital> iterable) {
Map<AREA, Integer> map = StreamSupport.stream(iterable.spliterator(), false)
.collect(Collectors.groupingBy(Hospital::getArea,
Collectors.summingInt(Hospital::getPatients)));
for (Map.Entry<AREA, Integer> area : map.entrySet())
System.out.println(area.getKey() + "...." + area.getValue());
return map.entrySet().stream()
.sorted((e1, e2) -> e2.getValue() - e1.getValue())
.collect(Collectors.toMap(Map.Entry::getKey,
Map.Entry::getValue, (o, o2) -> o,
LinkedHashMap::new));
}
Ясно, что я Итерировал дважды, чтобы найти десять областей с наибольшим количеством пациентов (один раз для группировки больниц по областям и расчета суммирования для этой группы и еще раз для поиска десяти областей с наибольшим числом пациентов).
Сейчас Я хочу знать:
1) Есть ли лучший подход для решения этой проблемы в одном потоке и, следовательно, в одной итерации?
2) Есть ли какое-либо преимущество в производительности для выполнения этого за одну итерацию, как лучше всего решить эту проблему? (С моей точки зрения, с одной стороны, когда я вызываю collect
, что является операцией терминала в первый раз использует мою итерацию и сохраняет промежуточный результат в другом объекте, в моем коде я назвал этот объект iterationOneResult, поэтому использование одного потока и вызов метода collect один раз пропустит этот промежуточный результат, что является основным преимуществом использования потока в java на другом ручное решение этой задачи за одну итерацию снижает сложность с O (2n) до O (n))