用枚举编码改进

时间:2019-07-02 16:17:13

标签: java

我有一个方法可以遍历部门中的Lectors(基本上是用户),并返回一个整数的JSON,该整数表示将哪个讲师分配给哪个程度(程度是一个枚举)

我在这里有方法:

    @Override
    public String getDepartmentStatistics(String departmentName) {
        List<Lector> lectorList = departmentRepository.getByName(departmentName).getLector();
        int assistantNumbers = 0;
        int associate_professorNumbers = 0;
        int professorNumbers = 0;
        for (Lector lector : lectorList) {
            if (lector.getLectorDegree().equals(ASSISTANT)) {
                assistantNumbers += 1;
            } else if (lector.getLectorDegree().equals(ASSOCIATE_PROFESSOR)) {
                associate_professorNumbers += 1;
            } else if (lector.getLectorDegree().equals(PROFESSOR)) {
                professorNumbers += 1;
            } else {
                return null;
            }
        }
        return String.valueOf(new JSONObject()
                .put("Assistants", assistantNumbers)
                .put("Associate professors", associate_professorNumbers)
                .put("Professors", professorNumbers));
    }

它按预期工作。

我的问题是如何改善其质量/外观?

3 个答案:

答案 0 :(得分:3)

您可以使用switch语句来检查度数,而不是多个if

@Override
public String getDepartmentStatistics(String departmentName) {
    List<Lector> lectorList = departmentRepository.getByName(departmentName).getLector();
    int assistantNumbers = 0;
    int associate_professorNumbers = 0;
    int professorNumbers = 0;

    for (Lector lector : lectorList) {
        switch(lector.getLectorDegree()) {
            case ASSISTANT:
                assistantNumbers += 1;
                break;

            case ASSOCIATE_PROFESSOR:
                associate_professorNumbers += 1;
                break;

            case ASSISTANT:
                professorNumbers += 1;
                break;

            default:
                return null;
        }
    }

    return String.valueOf(new JSONObject()
            .put("Assistants", assistantNumbers)
            .put("Associate professors", associate_professorNumbers)
            .put("Professors", professorNumbers));
}

答案 1 :(得分:2)

下面是一个使用Map来跟踪所有计数的示例:

enum Degree {
    PROFESSOR,
    ASSISTANT,
    ASSOCIATE_PROFESSOR
}

class Lector {
    Degree degree;

    public Degree getDegree() {
        return degree;
    }
}

public String getDepartmentStatistics(String departmentName) {
    List<Lector> lectorList = /*...*/
    Map<Degree, Integer> result = new EnumMap<>(Degree.class);

    lectorList.stream()
            .map(Lector::getDegree)
            .forEach(degree -> {
                Integer currentCount = result.getOrDefault(degree, 0);
                result.put(degree, ++currentCount);
            });

    return String.valueOf(new JSONObject()
            .put("Assistants", result.getOrDefault(Degree.ASSISTANT, 0))
            .put("Associate professors", result.getOrDefault(Degree.ASSOCIATE_PROFESSOR, 0))
            .put("Professors", result.getOrDefault(Degree.PROFESSOR, 0)));
}

您也可以通过流来代替Stream.forEach进行分组。您也可以使用Map.compute代替getOrDefault。这个版本是我主观上首选的解决方案,因为它可以很清楚地了解正在发生的事情。

与使用ifswitch相比,新的Degree值是开箱即用的(只有return语句不是通用的,但也可以泛化)。

编辑:安迪·特纳(Andy Turner)指出,使用Map.merge改进了解决方案:

public String getDepartmentStatistics(String departmentName) {
    List<Lector> lectorList = /*...*/
    Map<Degree, Integer> result = new EnumMap<>(Degree.class);

    lectorList.stream()
            .map(Lector::getDegree)
            .forEach(degree -> result.merge(degree, 1, Integer::sum));

    return String.valueOf(new JSONObject()
        .put("Assistants", result.getOrDefault(Degree.ASSISTANT, 0))
        .put("Associate professors", result.getOrDefault(Degree.ASSOCIATE_PROFESSOR, 0))
        .put("Professors", result.getOrDefault(Degree.PROFESSOR, 0)));
}

EDIT2: 让我包括一个完全功能性的方法,该方法不会将命令性方法和功能性方法混合使用过多(如评论中所述):

public String getDepartmentStatistics(String departmentName) {
    List<Lector> lectorList = /*...*/
    Map<Degree, Integer> result =
        lectorList.stream()
            .collect(Collectors.groupingBy(
                 Lector::getDegree,
                 () -> new EnumMap<>(Degree.class),
                 Collectors.counting()
            ));

    return String.valueOf(new JSONObject()
            .put("Assistants", result.getOrDefault(Degree.ASSISTANT, 0))
            .put("Associate professors", result.getOrDefault(Degree.ASSOCIATE_PROFESSOR, 0))
            .put("Professors", result.getOrDefault(Degree.PROFESSOR, 0)));
}

答案 2 :(得分:0)

考虑用策略或访问者列表替换if(或switch)语句 (我不确定在这种情况下哪个名称适用)。

这是一些示例代码(注意:我没有尝试编译此代码):

public enum LectorDegreeType
{
  ASSISTANT("Assistants"),
  ASSOCIATE_PROFESSOR("Associate Professors"),
  PROFESSOR("Professor");

  private final title;

  LectorDegreeType(final String titleValue)
  {
    title = titleValue;
  }

  public String getTitle()
  {
    return title;
  }
}

public interface LectorBlammy
{
  void blam(@NotNull Lector lector);
  void retrieveTitle();
  void retrieveTotal();
}

public abstract class AbstractLectorBlammy
implements LectorBlammy
{
  private final LectorDegreeType desiredDegree;
  private int matchCount;

  protected AbstractLectorBlammy(
  @NotNull final LectorDegreeType desiredDegreeValue)
  {
    desiredDegree = Objects.requireNotNull(desiredDegreeValue);

    matchCount = 0;
  }

  // perhaps make this a final method.
  public void blam(@NotNull final Lector lector)
  {
    if (lector.getLectorDegree().equals(desiredDegree))
    {
      ++matchCount;
    }
  }

  public void retrieveTitle()
  {
    return desiredDegree.getTitle();
  }

  public void retrieveTotal()
  {
    return matchCount;
  }
}

public class LectorBlammyAssistant
extends AbstractLectorBlammy
{
  public LectorBlammyAssistant()
  {
    AbstractLectorBlammy(LectorDegreeType.ASSISTANT);
  }
}

public class LectorBlammyAssociateProfessor
extends AbstractLectorBlammy
{
  public LectorBlammyAssistant()
  {
    AbstractLectorBlammy(LectorDegreeType.ASSOCIATE_PROFESSOR);
  }
}

public class LectorBlammyProfessor
extends AbstractLectorBlammy
{
  public LectorBlammyAssistant()
  {
    AbstractLectorBlammy(LectorDegreeType.PROFESSOR);
  }
}