【问题标题】:How to create a single HashMap member in a class for two different task with different initialization in two different constructors如何在一个类中为两个不同的任务创建单个 HashMap 成员,在两个不同的构造函数中进行不同的初始化
【发布时间】:2020-08-05 22:08:43
【问题描述】:

为有向图创建了两个 HashMap(g1 和 g2),为无向图创建了另一个,但我想要一个 HashMap 声明并在它们各自的构造函数中进行不同的初始化。

class Graphs<T, V>{

    public HashMap<T, LinkedList<T>> g1;
    public boolean[] visited;
    public HashMap<T, LinkedList<Pair<T, V>>> g2;

    static class Pair<T, V>{
        public T edge;
        public V w;

        Pair(T  i, V j){
            edge = i;
            w = j;
        }

        public String toString(){
            return "(" +edge + "," + w+ ")";
        }
    }

    Graphs(int size){
        g1 = new HashMap<>();
        visited = new boolean[size +1];
    }

    Graphs(int size, boolean weight){
        g2 = new HashMap<>();
        visited = new boolean[size +1];
    }

    public void addEdges(T u , T v){
        if(!g1.containsKey(u)){
            g1.put(u, new LinkedList<>());
        }
        if(!g1.containsKey(v)){
            g1.put(v, new LinkedList<>());
        }
        g1.get(u).add(v);
        g1.get(v).add(u);
    }

    public void addEdges(T u , T v , V w){
        if(!g2.containsKey(u)){
            g2.put(u, new LinkedList<>());
        }
        if(!g2.containsKey(v)){
            g2.put(v, new LinkedList<>());
        }

        g2.get(u).add(new Graphs.Pair<T, V>(v, w));
        g2.get(v).add(new Graphs.Pair<T, V>(u, w));
    }
}

【问题讨论】:

  • 我不太明白你在问什么。这段代码看起来像您试图使用单个类来表示两个根本不同的事物(如果您使用初始化 g1 的 ctor 创建一个图形,然后调用使用 g2addEdges 方法呢?) : 为什么不有两个单独的类?

标签: java oop generics hashmap


【解决方案1】:

类应该按照single-responsibility principle来设计:它们应该只做一件事。

你有一个类正在做两件事。因为这两个addEdges 方法采用不同的参数(和不同数量的参数),并使用它们来创建不同的东西,所以这些类所​​做的两个“东西”之间几乎没有共同点,除了它们都表示图。

您也许可以设法在两个分离的类之间共享一些逻辑;但是,老实说,这种设计比复制代码更糟糕。

class Graphs1<T>{

    public HashMap<T, LinkedList<T>> g1;
    public boolean[] visited;

    Graphs1(int size){
        g1 = new HashMap<>();
        visited = new boolean[size +1];
    }

    public void addEdges(T u , T v){
        g1.computeIfAbsent(u, k -> new LinkedList<>()).add(v);
        g1.computeIfAbsent(v, k -> new LinkedList<>()).add(u);
    }
}

class Graphs2<T, V>{

    public boolean[] visited;
    public HashMap<T, LinkedList<Pair<T, V>>> g2;

    // Pair declaration omitted.

    Graphs2(int size){
        g2 = new HashMap<>();
        visited = new boolean[size +1];
    }

    public void addEdges(T u , T v , V w){
        g2.computeIfAbsent(u, k -> new LinkedList<>()).add(new Graphs.Pair<>(v, w));
        g2.computeIfAbsent(v, k -> new LinkedList<>()).add(new Graphs.Pair<>(u, w));
    }
}

我想你可以像这样声明一个类:

class BaseGraph<T, E> {
  public HashMap<T, LinkedList<E>> g = new HashMap<>();
  public boolean[] visited;

  BaseGraph(int size) {
    this.visited = new boolean[size + 1];
  }

  protected void addEdge(T u, E value) {
    g.computeIfAbsent(u, k -> new LinkedList<>()).add(value);
  }
}

然后使它成为单独类中的成员:

class Graphs1<T> {
  BaseGraph<T, T> bg;

  Graphs1(int size) { bg = new BaseGraph<>(size); }

  public void addEdges(T u, T v) {
    bg.addEdge(u, v);
    bg.addEdge(v, u);
  }
}

class Graphs2<T, V> {
  BaseGraph<T, Pair<T, V>> bg;

  Graphs2(size) { bg = new BaseGraph<>(size); }

  public void addEdges(T u, T v) {
    bg.addEdge(u, new Pair<>(v, w));
    bg.addEdge(v, new Pair<>(u, w));
  }
}

我仍然不完全相信这比复制代码更值得。它只真正节省了addEdge 行。

【讨论】:

  • 我做这门课,这样当我不得不解决图形编码问题时。我不必做很多乏味的工作,即接受输入并创建图表。
  • Pair 类呢,它应该是一个独立的类还是其他类的内部。
  • 你可以在你喜欢的地方定义它。对于显示的代码,您只需要在Graphs2 中,因此您可以在那里定义它;如果您在其他类中需要它,您可以考虑将其定义为顶级类。
猜你喜欢
  • 1970-01-01
  • 2016-11-07
  • 2020-02-08
  • 2022-09-09
  • 2020-09-19
  • 2023-04-11
  • 2021-02-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多