java - Java中相同逻辑的泛化方法

标签 java generics refactoring

嗨,假设我们有一个包含许多数组列表的类,并且包含与下面非常相似的方法

public class Foo {
    private ArrayList<Rapper> rapperList = new ArrayList<>();
    private ArrayList<Musician> musicianList = new ArrayList<>();
    private ArrayList<Stadium> stadiumList = new ArrayList<>();

    public List<String> getRapperName() {
        ArrayList<String> rapperNameList = new ArrayList<>();
        for (Rapper r : rapperList) {
            rapperNameList.add(r.getRapperName());
        }
        return rapperNameList;
    } 

    public List<String> getMusicianName() {
        ArrayList<String> musicianNameList = new ArrayList<>();
        for (Musician m : musicianNameList) {
            musicianNameList.add(m.getMusicianName());
        }
        return musicianNameList;
    } //done

    public List<String> getStadiumID() {
        // exactly the same as above (using same logic)
    }

}

我省略了 getStadiumID 方法代码,因为它与上面的非常相似,并且所有方法都遵循相同的逻辑:

  • 列一个 list
  • 循环遍历对应的数组
  • 加入列表
  • 返回列表

我觉得有很多重复的代码,因为我基本上遵循相同的逻辑并且想知道是否有一种方法可以将这些方法简化为一个。我正在研究 Java 中的泛型,但似乎无法从中得到任何东西。

假设我的知识仅限于 Java 7(任何高于 7 的知识我都不知道 lambda 等)

最佳答案

本质上,您在这里所做的是映射列表中的每个元素:

return list.stream().map(fn).collect(Collectors.toList());

您可以将其包装在采用 List<T> list 的方法中和 Function<T, S> fn , 其中S是列表元素的类型(例如问题代码中的 String)。

private static <T, S> List<S> makeList(List<T> list, Function<T, S> fn) {
  return list.stream().map(fn).collect(Collectors.toList());
}

然后你可以这样调用:

public List<String> getRapperName() {
  return makeList(rapperList, Rapper::getRapperName);
}

public List<String> getMusicianName() {
  return makeList(musicianList, Musician::getMusicianName);
}

您可以在 Java 8 之前的代码中实现它;但它不会很漂亮。

首先,您需要一个 Function界面。您可以使用其他库中的 Guava;如果您不想依赖,也可以自己定义一个:

interface Function<T, S> {
  S apply(T input);
}

然后定义makeList方法:

private static <T, S> List<S> makeList(List<T> list, Function<T, S> fn) {
    ArrayList<String> result = new ArrayList<>();
    for (T t : list) {
        result.add(fn.apply(t));
    }
    return result;
}

然后像这样调用:

public List<String> getRapperName() {
  return makeList(rapperList, new Function<Rapper, String>() {
    @Override public String apply(Rapper r) {
      return r.getRapperName();
    }
  });
}

public List<String> getMusicianName() {
  return makeList(musicianList, new Function<Musician, String>() {
    @Override public String apply(Musician m) {
      return m.getMusicianName();
    }
  });
}

多乱七八糟的语法啊。

你可以通过拉动 Function 让它看起来更干净一点s out 变成常量等等;但老实说,这里的代码(以及非惯用代码)比您目前拥有的代码更多。

关于java - Java中相同逻辑的泛化方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49686306/

相关文章:

java - (龙头1.8) "stained_hardened_clay:14"!= "stained_hardened_clay:14"

JAVA:请帮助我使用compareTo对象

c - 重构遗留 C 代码——使用外部声明来帮助拆分模块(潜在的链接和运行时问题)

c - 从 C 代码项目中只提取所需的函数?

c# - 重构 session 检查

java - 从单个数组 Java 中添加和减去值

java - 为什么我的锯齿测试音不播放?

generics - PHPStan:具有泛型类的属性未指定其类型:TKey、T

Java Generics - 预期返回类型与实际不同

Java 重构为泛型行业标准