关于这些类,我正在尝试构建一个 map :
使用这些简单的类结构
class Alert {
public String serie;
public String rame;
public String label;
public Alert( String serie, String rame, String label ) {
this.serie = serie;
this.rame = rame;
this.label = label;
}
public String getSerie() {
return serie;
}
public String getRame() {
return rame;
}
public String getLabel() {
return label;
}
}
class Diagnostic {
public String serie;
public String rame;
public List< Event > events;
public Diagnostic(String serie, String rame){
this.serie = serie;
this.rame = rame;
}
public void addEvent(String label){
if(events == null)events = new ArrayList<>( );
events.add( new Event( label ) );
}
}
class Event {
public String label;
public Event(String label){
this.label = label;
)}
}
Alert atgv1 = new Alert( "tgv", "rame1", "label1" );
Alert atgv2 = new Alert( "tgv", "rame1", "label2" );
Alert atgv3 = new Alert( "tgv", "rame1" , "label3");
Alert atgv4 = new Alert( "tgv", "rame2", "label4" );
Alert atgv5 = new Alert( "tgv", "rame2", "label5" );
Alert atgv6 = new Alert( "tgv", "rame3", "label6" );
Alert az2n1 = new Alert( "z2n", "rame1", "label1" );
Alert az2n2 = new Alert( "z2n", "rame1", "label2" );
Alert az2n3 = new Alert( "z2n", "rame1" , "label3");
Alert az2n4 = new Alert( "z2n", "rame2", "label4" );
Alert az2n5 = new Alert( "z2n", "rame2", "label5" );
Alert az2n6 = new Alert( "z2n", "rame3", "label6" );
List<Alert> alerts = Arrays.asList(atgv1, atgv2, atgv3, atgv4, atgv5, atgv6, az2n1, az2n2, az2n3, az2n4, az2n5, az2n6);
我有这个有效的代码:
Map<String, Map<String, Diagnostic>> map = alerts.stream()
.collect(Collectors.collectingAndThen( Collectors.groupingBy( Alert::getSerie,
Collectors.toMap( Alert::getRame, a -> new Diagnostic( a.getSerie(), a.getRame() ), (a1, a2) -> a1)), b -> {
b.forEach( ( k, v ) -> v.forEach( ( y, z) -> {
List<Alert> found = alerts.stream().filter( p -> p.getSerie().equals( k ) && p.getRame().equals( y ) ).collect( Collectors.toList());
found.forEach( f -> z.addEvent( f.getLabel() ) );
}) );
return b;
} ));
结果是我想要的,但问题是我在 andThen
中的 map 上循环,以便找到正确的警报(过滤器)并添加事件 (.addEvent)
如何一次性实现?是否可以不编写自己的Collector
?
困难的部分是我想要一个带有事件列表的诊断列表,而不是我可以使用第二个 groupingBy
而不是 toMap
轻松实现的诊断列表。 .
最佳答案
您可以使用多个groupingBy
来解决问题,然后您需要减少
诊断
值:
Map<String, Map<String, Optional<Diagnostic>>> map = alerts.stream()
.collect(Collectors.groupingBy(Alert::getSerie,
Collectors.groupingBy(Alert::getRame,
Collectors.mapping(e -> new Diagnostic(e.getSerie(), e.getRame()),
Collectors.reducing((d1, d2) -> Diagnostic.builder()
.serie(d1.getSerie())
.rame(d1.getRame())
.events(Stream.concat(d1.getEvents().stream(),
d2.getEvents().stream()).collect(Collectors.toList()))
.build())))));
注意:上面依赖于我使用的 Builder
,以便于创建 Diagnostic
实例,其中涉及添加事件,并且它收集最里面的值作为可选
,以应对缺乏可依赖的标识元素。
或者如 Holger 的回答,using toMap(f1, f2, f3)
instead of groupingBy(f1, mapping(f2, reducing(f3)))
将是嵌套收集操作的首选操作,如下所示:
Map<String, Map<String, Diagnostic>> map = alerts.stream()
.collect(Collectors.groupingBy(Alert::getSerie,
Collectors.toMap(Alert::getRame, e -> new Diagnostic(e.getSerie(), e.getRame()),
(d1, d2) -> Diagnostic.builder()
.serie(d1.getSerie())
.rame(d1.getRame())
.events(Stream.concat(d1.getEvents().stream(),
d2.getEvents().stream()).collect(Collectors.toList()))
.build())));
关于java - 使用哪些收集器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59308431/