@Override
    public void removeEdge(Vertex<T> source, Vertex<T> destination) {
        if (!vertexes.containsKey(source)) {
            throw new RuntimeException("There is no vertex in graph " + source);
        }

        if (!vertexes.containsKey(destination)) {
            throw new RuntimeException("There is no vertex in graph " + destination);
        }

        Edge<T> edge = new Edge<T>(source, destination);
        Edge<T> opposite = new Edge<T>(destination, source);

        if (!isEdge(source, destination)) {
            throw new RuntimeException("There is no edge to delete " + edge);
        }


        //As we have non directed graph V1->V2 is the same as V2->V1
        if (edges.get(edge) != null) {
            Integer occurences = edges.get(edge);
            if (occurences == 1) {
                edges.remove(edge);
            } else {
                edges.put(edge, occurences - 1);
            }
            vertexes.get(source).getEdges().remove(edge);
            vertexes.get(destination).getEdges().remove(edge);
            vertexes.get(source).getEdges().remove(opposite);
            vertexes.get(destination).getEdges().remove(opposite);
        }


        if (edges.get(opposite) != null) {
            Integer occurences = edges.get(opposite);
            if (occurences == 1) {
                edges.remove(opposite);
            } else {
                edges.put(opposite, occurences - 1);
            }
            vertexes.get(source).getEdges().remove(opposite);
            vertexes.get(destination).getEdges().remove(opposite);
            vertexes.get(source).getEdges().remove(edge);
            vertexes.get(destination).getEdges().remove(edge);
        }
    }