J'ai un flux de MetricGroup
, où:
< MetricGroup("app1", 2, 400) , MetricGroup("app2", 1, 200) >
Je dois résumer toutes les métriques d'application. Je veux dire, pour chaque application ( MetricGroup.application
), je dois ajouter tous les metric.uploadedDocs
dans une métrique sumMetric.uploadedDocs
et .uploadedKds
dans un sumMetric.uploadedKbs
.
Je suppose que j'ai besoin d'une sorte de groupingBy
Stream.of( new MetricGroup("app1", 1,100), new MetricGroup("app1", 1,300), new MetricGroup("app2", 1,200) ) .collect(Collector.groupingBy(MetricGroup::getApplication, accumulator??, combiner??)
Le résultat serait un flux avec:
public class MetricGroup { private String application; private int uploadedDocs; private long uploadedKbs; // getters and setters }
Des idées?
4 Réponses :
Vous pouvez regrouper par application
puis mapper les résultats sur MetricGroup
:
source.stream() .collect(groupingBy(MetricGroup::getApplication)) .entrySet().stream() .map(s -> new MetricGroup(s.getKey(), s.getValue().stream().mapToInt(MetricGroup::getUploadedDocs).sum(), s.getValue().stream().mapToLong(MetricGroup::getUploadedKbs).sum())) .collect(Collectors.toList());
vous pouvez essayer quelque chose comme ceci
groupedByAppKbs.get("app1").longValue();
Que pour accéder aux vaues:
private static final List<MetricGroup> mgArr = Arrays.asList(new MetricGroup("app1", 1,100),new MetricGroup("app1", 1,300),new MetricGroup("app2", 1,200)); Map<String, Long> groupedByAppKbs = mgArr.stream() .collect(groupingBy(MetricGroup::getApplication, summingLong(MetricGroup::getUploadedKbs)));
Si vous pouviez ajouter le constructeur de copie et la méthode merge
suivants à la classe MetricGroup
:
Map<String, MetricGroup> result = Stream.of( new MetricGroup("app1", 1,100), new MetricGroup("app1", 1,300), new MetricGroup("app2", 1,200)) .collect(Collectors.toMap( MetricGroup::getApplication, MetricGroup::new, // use copy constructor MetricGroup::merge)); // use MetricGroup.merge method
Ensuite, vous pouvez utiliser Collectors.toMap pour regrouper les métriques par application:
public MetricGroup(MetricGroup another) { this.application = another.application; this.uploadedDocs = another.uploadedDocs; this.uploadedKbs = another.uploadedKbs; } public MetricGroup merge(MetricGroup another) { this.uploadedDocs += another.uploadedDocs; this.uploadedKbs += another.uploadedKbs; return this; }
Notez que nous devons utiliser le constructeur de copie pour ne pas muter le MetricGroup code> éléments du flux.
Utilisez Collectors.reducing
lors du regroupement par MetricGroup.application
:
Map<String, MetricGroup> collect = source.stream() .collect( groupingBy(MetricGroup::getApplication, reducing(new MetricGroup(null, 0, 0), (m1, m2) -> new MetricGroup( m2.application, m1.getUploadedDocs() + m2.getUploadedDocs(), m1.getUploadedKbs() + m2.getUploadedKbs()))));
Quel est le problème avec les réponses que vous avez obtenues à votre question similaire posée il y a 30 minutes ?
J'ai besoin de regrouper par application, sur l'autre poste seulement, je dois résumer tous les objets. Maintenant, je dois résumer par application.