避免在数组中重复条目

时间:2013-11-20 17:22:23

标签: java arrays duplicates

我正在编写一个将Vertex对象添加到数组的方法。我需要检查我添加的顶点是否已存在于数组中。我不确定我哪里出错了。这是我的方法:

public void addVertex(Vertex v) {
    if (activeVertices >= maxVertices) {
        System.out.println("Graph full");
        return;
    }
    for(int i=1; i<vertices.length; i++) {
        if(vertices[i] != vertices[i-1]){
            vertices[activeVertices] = v; // add vertex to list of vertices
            v.graphIndex = activeVertices; // record index of vertex in graph
            activeVertices++;  // increment vertex count
        }
    }
}

顶点类:

public class Vertex {
    public String name;
    public int graphIndex; // index of adjacency matrix position of node in graph

    public Vertex (String s) {
        name = s;
        graphIndex = -1; // invalid position by default 
    }

    public String toString() {
        return name;
    }

}

包含addVertex()方法的类:

public class Graph {
    private int maxVertices;
    private Vertex[] vertices; // array of nodes
    private int[][] edges; // adjacency matrix
    int activeVertices;


    public Graph(int maxSize) {
        maxVertices = maxSize;
        vertices = new Vertex[maxVertices];
        activeVertices = 0;
    }


    public void addVertex(Vertex v) {
        if (activeVertices >= maxVertices) {
            System.out.println("Graph full");
            return;
        }
        for(int i=1; i<vertices.length; i++) {
            if(vertices[i] != vertices[i-1]){
                vertices[activeVertices] = v; // add vertex to list of vertices
                v.graphIndex = activeVertices; // record index of vertex in graph
                activeVertices++;  // increment vertex count
            }
        }
    }
    public void addEdge(Vertex v1, Vertex v2, int w) {
        edges[v1.graphIndex][v2.graphIndex] = w;
        edges[v2.graphIndex][v1.graphIndex] = w;
    }

    public Graph minimumSpanningTree() {
        Graph mst = new Graph(maxVertices); // create new graph
        int[] set = new int[activeVertices];
        for (int i=0; i<activeVertices; i++) { // copy nodes to graph
            mst.addVertex(vertices[i]);
            set[i]=i; // assign each node to its own set
        }
        PriorityQueue q = new PriorityQueue(maxVertices*maxVertices); // create priority queue
        for (int i=0; i<activeVertices; i++) { // copy edges to queue
            for (int j=0; j<activeVertices; j++) { 
                if (edges[i][j]!=0) {
                    q.enqueue(new Edge(vertices[i],vertices[j],edges[i][j]));
                }
            }
        }

        while (!q.isEmpty()) { // iterate over all edges in priority order
            Edge e = q.dequeue(); // consider next edge
            if (set[e.source.graphIndex]!=set[e.destination.graphIndex]) { // skip edges not connecting different sets
                mst.addEdge(e.source, e.destination, e.weight); // add edge to MST
                System.out.println("adding "+e);
                int setToMerge=set[e.destination.graphIndex]; // rename nodes from "other" set
                for (int i=0; i<activeVertices; i++) {
                    if (set[i]==setToMerge) { // find nodes from "other" set
                        set[i]=set[e.source.graphIndex]; // reassign nodes
                    }
                }
            }
        }
        return mst;
    }

    public void print() {
        System.out.format("    ");
        for (int i=0; i<activeVertices; i++) {
            System.out.format("%3s ", vertices[i].name);
        }
        System.out.format("\n");
        for (int j=0; j<activeVertices; j++) {
            System.out.format("%3s ", vertices[j].name);
            for (int i=0; i<activeVertices; i++) {
                System.out.format("%3d ", edges[i][j]);
            }
            System.out.format("\n");
        }
    }
}

3 个答案:

答案 0 :(得分:1)

首先,您应该使用equals而不是==。您应该在equals课程中编写正确的Vertex方法(使用Google查找大量有关如何执行此操作的教程)。

例如,如果您希望两个Vertex对象只有在它们的名称相同时才被认为是相同的,那么您的equals方法将如下所示:

public boolean equals(Object obj) {
    if(obj == null) {
        return false;
    }

    if(obj instanceof Vertex) {
        Vertex otherVertex = (Vertex) obj;
        if(this.name.equals(otherVertex.name)) {
            return true;
        }
    }
    return false;
}

如果您还想比较graphIndex,那么您还需要在equals方法中进行检查。

假设您的equals类中有一个正确的Vertex方法,最简单的解决方案是使用来自Apache Commons库的ArrayUtils.contains方法(Apache Commons有很多有用的东西)方法,可以节省你很多时间。你应该检查出来)。此方法接受一个数组和一个Object,并检查数组是否包含该对象。

答案 1 :(得分:0)

您始终针对vertices[1]检查vertices[0]并根据结果进行添加。你没有检查v,也没有查看整个数组。

如果==检查(身份,而不是等同)真的是你想要的,那么:

public void addVertex(Vertex v) {
    if (activeVertices >= maxVertices) {
        System.out.println("Graph full");
        return;
    }
    for(int i=0; i<vertices.length; i++) {
        if(vertices[i] == v){
            // Already have it
            return;
        }
    }
    vertices[activeVertices] = v; // add vertex to list of vertices
    v.graphIndex = activeVertices; // record index of vertex in graph
    activeVertices++;  // increment vertex count
}

如果您想要等效,请替换

if(vertices[i] == v){

if(v.equals(vertices[i])){

附注:根据您拥有activeVertices变量,我怀疑您使用ArrayList<Vertex>而不是Vertex[]可能会更好。这也会为您提供contains方法(使用equals),它可以替换您的循环(如果您想要equals,而不是==,请检查)

答案 2 :(得分:0)

每当您编写值类时,即表示某事物的值或数量的类时,您应始终为您的类重写以下方法:

  • equals(Object o);
  • 的hashCode();

并非所有类都是值类。有些代表系统资源,有些代表行为或进程,但只要将类编写为数据集的抽象,就应该考虑编写上述方法。

原因很简单。虽然Java原语只具有价值,但Java引用类型(包括您自己编写的所有类的实例)都具有值和位置。这赋予引用类型相等和同一性的属性,它们是非常不同的。

默认情况下,Object类中的equals()方法执行身份比较, NOT 执行相等比较......这也是一件好事。因为Object的任何子类可能具有截然不同的“如何将实例视为相等”的概念,所以没有直接的方法可以使用一个超类方法来测试任意Java对象的相等性。相比之下,测试身份总是直截了当的。如果任何两个引用指示相同的位置,则它们的对象是相同的。这体现了不同的平等和认同概念。

您需要能够测试您的Vertex实例是否相等以及它们是否相同。因此,您确实需要覆盖equals(Object o)方法。如果你也覆盖hashCode()(你应该),那么你可以将你的顶点存储在一个HashSet中,这样可以保证两个顶点不相等。