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

huangapple go评论73阅读模式
英文:

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 Pair<T, V>(v, w));
        g2.get(v).add(new Pair<T, V>(u, w));
    }
}
英文:

Two HashMaps (g1 and g2) are created for the directed graph and another one for the undirected graph, but I want, with one declaration of HashMap and different initialization in their respective constructor.

class Graphs&lt;T, V&gt;{
public HashMap&lt;T, LinkedList&lt;T&gt;&gt; g1;
public boolean[] visited;
public HashMap&lt;T, LinkedList&lt;Pair&lt;T, V&gt;&gt;&gt; g2;
static class Pair&lt;T, V&gt;{
public T edge;
public V w;
Pair(T  i, V j){
edge = i;
w = j;
}
public String toString(){
return &quot;(&quot; +edge + &quot;,&quot; + w+ &quot;)&quot;;
}
}
Graphs(int size){
g1 = new HashMap&lt;&gt;();
visited = new boolean[size +1];
}
Graphs(int size, boolean weight){
g2 = new HashMap&lt;&gt;();
visited = new boolean[size +1];
}
public void addEdges(T u , T v){
if(!g1.containsKey(u)){
g1.put(u, new LinkedList&lt;&gt;());
}
if(!g1.containsKey(v)){
g1.put(v, new LinkedList&lt;&gt;());
}
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&lt;&gt;());
}
if(!g2.containsKey(v)){
g2.put(v, new LinkedList&lt;&gt;());
}
g2.get(u).add(new Graphs.Pair&lt;T, V&gt;(v, w));
g2.get(v).add(new Graphs.Pair&lt;T, V&gt;(u, w));
}
}

答案1

得分: 0

根据单一责任原则,类应该根据设计,只做一件事情。

你有一个类,它正在执行两件事情。因为这两个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 Pair<>(v, w));
        g2.computeIfAbsent(v, k -> new LinkedList<>()).add(new 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, V w) {
    bg.addEdge(u, new Pair<>(v, w));
    bg.addEdge(v, new Pair<>(u, w));
  }
}

我仍然不完全确定这是否值得,与仅复制代码相比。这只是在addEdge行上节省了一些代码。

英文:

Classes should be designed according to the single-responsibility principle: they should only do one thing.

You've got a class which is doing two things. Because the two addEdges methods take different parameters (and different numbers of parameters), and use those to create different things, there is little in common between the two "things" these classes do, beyond the fact they both represent graphs.

You could perhaps contrive to share some logic between two separated classes; but, honestly, the contrivance would be worse than just duplicating the code.

class Graphs1&lt;T&gt;{
public HashMap&lt;T, LinkedList&lt;T&gt;&gt; g1;
public boolean[] visited;
Graphs1(int size){
g1 = new HashMap&lt;&gt;();
visited = new boolean[size +1];
}
public void addEdges(T u , T v){
g1.computeIfAbsent(u, k -&gt; new LinkedList&lt;&gt;()).add(v);
g1.computeIfAbsent(v, k -&gt; new LinkedList&lt;&gt;()).add(u);
}
}
class Graphs2&lt;T, V&gt;{
public boolean[] visited;
public HashMap&lt;T, LinkedList&lt;Pair&lt;T, V&gt;&gt;&gt; g2;
// Pair declaration omitted.
Graphs2(int size){
g2 = new HashMap&lt;&gt;();
visited = new boolean[size +1];
}
public void addEdges(T u , T v , V w){
g2.computeIfAbsent(u, k -&gt; new LinkedList&lt;&gt;()).add(new Graphs.Pair&lt;&gt;(v, w));
g2.computeIfAbsent(v, k -&gt; new LinkedList&lt;&gt;()).add(new Graphs.Pair&lt;&gt;(u, w));
}
}

I suppose you could declare a class something like:

class BaseGraph&lt;T, E&gt; {
public HashMap&lt;T, LinkedList&lt;E&gt;&gt; g = new HashMap&lt;&gt;();
public boolean[] visited;
BaseGraph(int size) {
this.visited = new boolean[size + 1];
}
protected void addEdge(T u, E value) {
g.computeIfAbsent(u, k -&gt; new LinkedList&lt;&gt;()).add(value);
}
}

and then make this a member inside the separate classes:

class Graphs1&lt;T&gt; {
BaseGraph&lt;T, T&gt; bg;
Graphs1(int size) { bg = new BaseGraph&lt;&gt;(size); }
public void addEdges(T u, T v) {
bg.addEdge(u, v);
bg.addEdge(v, u);
}
}
class Graphs2&lt;T, V&gt; {
BaseGraph&lt;T, Pair&lt;T, V&gt;&gt; bg;
Graphs2(size) { bg = new BaseGraph&lt;&gt;(size); }
public void addEdges(T u, T v) {
bg.addEdge(u, new Pair&lt;&gt;(v, w));
bg.addEdge(v, new Pair&lt;&gt;(u, w));
}
}

I'm still not entirely convinced this is worthwhile over just duplicating the code. It only really saves on the addEdge lines.

huangapple
  • 本文由 发表于 2020年8月6日 06:08:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/63274208.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定