java - 使用哪些收集器?

标签 java lambda java-8 java-stream collectors

关于这些类,我正在尝试构建一个 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/

相关文章:

java - 存储库找到 3 条记录,结果列表返回 6 条记录

java - ASCII 中的六个不同的 '?' 字符?

c# - linq to entities dynamic where 从 lambdas 构建

Java:在 JAR 中嵌入 Soundbank 文件

java - 如何配置 Ehcache 重新计算 key 而不是逐出?

c++ - 通用 vector 类中的重载解析问题

java - Lambda 表达式创建以整数为键、以列表为值的映射

java - 如何将这个经典的 Java 代码重写为 Java Stream API 代码?

java - 将两个List<>映射到HashMap

java - 如何根据给定条件使用 Comparator.comparing() 对类进行排序