Implementation of generic Graph class and Dijkstras I participate in competitive programming contests, and I found myself implementing and re-implementing graphs constantly. So I decided to create a reusable implementation of a Graph class, and implement some common methods for it, including DFS, BFS, and Dijkstras.

Are there any edge cases that my code misses? Is there anything I could do to improve it?

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Stack;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;

public class Graph&lt;T&gt; {

    public class Node {
        public T value;
        public Map&lt;Integer, Integer&gt; edges;

        public Node(T value) {
            this.value = value;
            edges = new HashMap&lt;&gt;();
        }
    }

    public List&lt;Node&gt; nodes;

    public boolean directed;
    public int numNodes = 0;
    public int numEdges = 0;

    public Graph() {
        this(false);
    }

    public Graph(boolean directed) {
        nodes = new ArrayList&lt;&gt;();
        this.directed = directed;
    }

    public void addNode(T value) {
        nodes.add(new Node(value));
    }

    public void connect(int i, int j, int weight) {
        nodes.get(i).edges.put(j, weight);
        if (!directed)
            nodes.get(j).edges.put(i, weight);
    }

    public class DijkstrasNode extends Node {
        int dist = -1;
        boolean visited = false;
        DijkstrasNode previous;

        public DijkstrasNode(T value) {
            super(value);
        }

        public DijkstrasNode(Node node) {
            super(node.value);
            this.edges = node.edges;
        }
    }

    public void processBFS(int source, BiConsumer&lt;Node, Integer&gt; consumer) {
        Queue&lt;Integer&gt; q = new LinkedList&lt;&gt;();
        boolean[] visited = new boolean[nodes.size()];
        q.add(source);
        while (!q.isEmpty()) {
            int id = q.poll();
            if (visited[id])
                continue;
            visited[id] = true;
            Node n = nodes.get(id);
            consumer.accept(n, id);
            for (int c: n.edges.keySet())
                q.add(c);
        }
    }

    public void processDFS(int source, BiConsumer&lt;Node, Integer&gt; consumer) {
        Stack&lt;Integer&gt; q = new Stack&lt;&gt;();
        boolean[] visited = new boolean[nodes.size()];
        q.push(source);
        while (!q.isEmpty()) {
            int id = q.pop();
            if (visited[id])
                continue;
            visited[id] = true;
            Node n = nodes.get(id);
            consumer.accept(n, id);
            for (int c: n.edges.keySet())
                q.add(c);
        }
    }

    public List&lt;DijkstrasNode&gt; dijkstras(int source) {
        List&lt;DijkstrasNode&gt; djk = nodes.stream().map(DijkstrasNode::new).collect(Collectors.toList());
        djk.get(source).dist = 0;
        PriorityQueue&lt;DijkstrasNode&gt; q = new PriorityQueue&lt;&gt;((i, j) -&gt; i.dist - j.dist);
        q.add(djk.get(source));
        int visitCount = 0;
        while (!q.isEmpty() &amp;&amp; visitCount &lt; djk.size()) {
            DijkstrasNode n = q.poll();
            if (n.visited)
                continue;
            n.visited = true;
            visitCount++;
            for (int child : n.edges.keySet()) {
                DijkstrasNode cn = djk.get(child);
                if (!cn.visited &amp;&amp; (cn.dist == -1 || n.dist + n.edges.get(child) &lt; cn.dist)) {
                    if (cn.dist != -1)
                        q.remove(cn);
                    cn.dist = n.dist + n.edges.get(child);
                    cn.previous = n;
                    q.add(cn);
                }
            }
        }
        return djk;
    }

}
Just a small remark design-wise:

I think you should not extend Node to DijkstraNode, but rather have a Node&lt;Dijkstra&gt;.  Or, if you intent to store info in the DijkstraNode, have a Node&lt;Dijkstra&lt;T&gt;&gt;.