Java - 根据唯一 ID 收集、删除类的属性(全部扩展父类(super class))

标签 java java-8

好的,这就是我的问题。

我有一个“父类(super class)”,我将其称为“动物”。每个“动物”都有一个唯一的ID

public class Animal {

    @Id
    private ObjectId id;
}

我有几个扩展“动物”的类(狮子、斑马、企鹅......)

public class Penguin extends Animal...

最后,我有一个名为“NoahsArk”的类,它拥有特定的“动物”属性,例如

public class NoahsArk {

    private Zebra zebra;

    private Lion lion;

    private Penguin penguin;

}

最后,我想做几件事:

  1. 能够返回我的“诺亚方舟”的“动物”列表
  2. 能够返回 ID 等于给定 ID 的“动物”(给定 #1,我知道如何做到这一点)
  3. 能够删除(设置为 null)ID 等于给定 ID 的“动物”

我知道在如此简单的情况下,对于#1,我只需要做类似的事情

public List<Animal> getAnimals() {
    List<Animal> animals= new ArrayList<>();
    if (lion != null) {
        animals.add(lion);
    }
    ...
    return animals;
}

对于#2,我可以简单地这样做

public Animal getAnimalById(String id) {
        return getAnimals().stream().filter(a -> a.getId().toString().equals(id)).findFirst().orElse(null);
    }

但是我们假设诺亚方舟有很多“动物”,它们没有存储在 List<Animal> 中但单独声明。

在这种情况下,是否有一种有效的方法(至少在编写代码行方面)来完成#1 和#3 的操作?

对于 #3,我的第一 react 是使用 #1 的输出,然后将 ID 与输入匹配的“Animal”设置为 null,但这行不通。

最佳答案

正因为您必须提供 getter 和 setter 方法,所以您不必将每个值存储到其自己的字段中。封装的意义在于自由选择内部表示:

public class NoahsArk {
    private final Map<Class<? extends Animal>, Animal> stored = new HashMap<>();
    private <A extends Animal> A get(Class<A> type) {
      return type.cast(stored.get(type));
    }
    private <A extends Animal> void set(Class<A> type, A animal) {
      if(animal == null) stored.remove(type);
      else stored.put(type, animal);
    }
    public Zebra getZebra() {
      return get(Zebra.class);
    }
    public void setZebra(Zebra zebra) {
      set(Zebra.class, zebra);
    }
    public Lion getLion() {
      return get(Lion.class);
    }
    public void setLion(Lion lion) {
      set(Lion.class, lion);
    }
    public Penguin getPenguin() {
      return get(Penguin.class);
    }
    public void setPenguin(Penguin penguin) {
      set(Penguin.class, penguin);
    }
    public List<Animal> getAll() {
      return new ArrayList<>(stored.values());
    }
    public void remove(ObjectId id) {
      stored.values().removeIf(a -> a.getId().equals(id));
    }
}

您可以拥有从 id 到动物的映射,而不是从类型到动物的映射,从而使 remove 更加高效,但代价是 getter 和 setter 效率较低。或者您拥有两个映射,使所有操作都变得更快,但内存消耗更高,并且需要更加小心才能使两者处于一致状态。

在现实生活中,我会先向客户询问清楚。不是应该各有两个吗?否则,您最终可能会得到一个完全符合规范的软件,但客户仍然不满意......

关于Java - 根据唯一 ID 收集、删除类的属性(全部扩展父类(super class)),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60736818/

相关文章:

java - Apache nutch 错误 NoClassDefFoundError "com/google/protobuf/Message"

java - kdb q - 尽管设置了 $QHOME,但仍未找到许可证

java - 在 Stream 的 collect() 终端操作中,如果 supplier 是一个像 String 这样的不可变对象(immutable对象)会怎样?

lambda - 如何将参数传递给 Java 8 Lambda 流函数?

java - 如何使用 C10N 库使类返回翻译后的字符串

java - 在 Java 或 .NET 中,如何创建监听特定端口的服务器?

lambda - Java 8 lambda 不更改数据

collections - 在 Java 中将枚举转换为映射

Java 8 Streams map API - 方法引用解读

java - 将并行数组流简化为单个数组