Как создать один член HashMap в классе для двух разных задач с разной инициализацией в двух разных конструкторах - PullRequest
0 голосов
/ 06 августа 2020

Две 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));
    }
}

1 Ответ

0 голосов
/ 06 августа 2020

Классы должны быть разработаны в соответствии с принципом единой ответственности : они должны делать только одно.

У вас есть класс, который выполняет две задачи. Поскольку два метода addEdges принимают разные параметры (и разное количество параметров) и используют их для создания разных вещей, между двумя «вещами», которые выполняют эти классы, мало общего, помимо того факта, что они оба представляют графики.

Возможно, вы могли бы придумать общий c logi * между двумя разделенными классами; но, честно говоря, это было бы хуже, чем просто дублирование кода.

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 строках.

...