【问题标题】:Accept generic List as parameter and use it base on its type接受泛型 List 作为参数并根据其类型使用它
【发布时间】:2019-04-03 09:42:50
【问题描述】:

我正在为我的公司开发一个网站,我使用 Spring 作为我的后端。 现在有一种情况,我需要两次使用我的 Utils 方法之一,但用于不同的 DAO。

为了避免代码重复,我想知道如何使用 Java 泛型以使此方法可用于两种情况。该方法只计算两个 DAO 共有的字段之一。

实用方法:

SeverityCount calculateSeveritiesCount(List<?> events){

        if(null == events){
            return new SeverityCount();
        }

        if(events.get(1) instanceof EventDAO){
            events = (List<EventDAO>)events;
        }
        else if (events.get(1) instanceof EventsByAreaDAO) {
            events = (List<EventsByAreaDAO>)events;
        }

        Map<String, Long> severityCountMap = events.stream().collect(
            Collectors.groupingBy(
                EventDAO::getSeverity,  //It should be EventDAO or EventsByAreaDAO. both has severity field.
                Collectors.counting())
        );

        return mapper.convertValue(severityCountMap, SeverityCount.class);
    }

事件 DAO:

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "events")
public class EventDAO {
    @Id @Column(name = "uid")
    private String uID;

    private String date;

    private String severity;

}

区域 DAO:

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "events")
public class EventsByRegionDAO {

     @Id @Column(name = "uid")
    private String uID;

    private String date;

    private String type;

    private String severity;

    private String area;

    private String server;
}

这是我从服务中调用它的方式:

SeverityCount severitiesCount = Utils.calculateSeveritiesCount(eventsList);  //EventsList could be list of EventDAO or EventsByAreaDAO

【问题讨论】:

  • 你能为他们创建一个通用接口吗?
  • 由于这一行,我显示的代码不起作用:EventDAO::getSeverity,在 utils 方法中。我需要根据收到的列表类型定义 DAO 的类型
  • 对,我删除了该评论...请再次阅读另一个评论并告诉我们

标签: java spring list generics


【解决方案1】:

你可以把方法改成

SeverityCount calculateSeveritiesCount(List<? extends SeverityCalculable> events)

在哪里SeverityCalculable

interface SeverityCalculable {
    String getSeverity(); // implemente getter in all subclasses
}

让所有相关的类都实现这个接口。

public class EventDAO implements SeverityCalculable  {

    // ...

    @Override
    public String getSeverity() {
        return this.severity;
    }
}

现在在你的方法中,移除演员表,它应该变成这样:

 SeverityCount calculateSeveritiesCount(List<? extends SeverityCalculable> events) {

    if(null == events){
        return new SeverityCount();
    }

    Map<String, Long> severityCountMap = events.stream().collect(
        Collectors.groupingBy(
            SeverityCalculable::getSeverity,
            Collectors.counting()
        )
    );

    return mapper.convertValue(severityCountMap, SeverityCount.class);
}

【讨论】:

    【解决方案2】:

    由于两个 DAO 都有一个 severity 属性,它们可能会实现一个通用接口,例如 SeverityAware

    public interface SeverityAware {
      public String getSeverity();
    }
    
    public class EventsByRegionDAO implements SeverityAware { .. }
    
    public class EventDAO implements SeverityAware { .. }
    

    此外,您的方法现在可以接受此接口的子类型:

    SeverityCount calculateSeveritiesCount(List<? extends SeverityAware> events){
    
      if (null == events){
        return new SeverityCount();
      }
    
      Map<String, Long> severityCountMap = events.stream().collect(Collectors.groupingBy(
        SeverityAware::getSeverity,Collectors.counting())
      );
    
      return mapper.convertValue(severityCountMap, SeverityCount.class);
    }
    

    【讨论】:

    • 我承认SeverityAware 听起来比SeverityCalculable
    • @MarkoPacak “通用”命名如何 [SomeThingItDoes] + [able] -> Severityable ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多