Принять общий список в качестве параметра и использовать его в зависимости от его типа - PullRequest
5 голосов
/ 03 апреля 2019

Я разрабатываю веб-сайт для своей компании и использую Spring в качестве бэкэнда.Сейчас есть ситуация, когда мне нужно использовать один из моих методов Utils дважды, но для разных DAO.

Чтобы избежать дублирования кода, мне было интересно, как я могу использовать Java Generics для того, чтобы сделать этометод применим для обоих случаев.Метод просто подсчитывает одно из полей, общее для обоих DAO.

Метод Util:

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 ]

5 голосов
/ 03 апреля 2019

Вы можете изменить метод на

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);
}
4 голосов
/ 03 апреля 2019

Поскольку оба 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...