如何在 class 中为两个不同的任务在两个不同的构造函数中使用不同的初始化创建单个 HashMap 成员

How to create a single HashMap member in a class for two different task with different initialization in two different constructors

为有向图创建了两个 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));
    }
}

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

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

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

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 类似的东西:

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);
  }
}

然后使它成为单独的 classes:

中的成员
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 行。