接受通用列表作为参数,并根据其类型使用它

时间:2019-04-03 09:42:50

标签: java spring list generics

我正在为我的公司开发一个网站,我使用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

2 个答案:

答案 0 :(得分:5)

您可以将方法更改为

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);
}

答案 1 :(得分:4)

由于两个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);
}