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.