java - 为什么此类的compareTo 方法没有将边<A,B> 和<B,A> 返回为同一事物?

标签 java graph

这里(下方)是我的 MovieEdge 类;没什么特别的,它指向 2 个 Actor 对象,它们是这条边的顶点。此外,这是一个未加权和无向图,但我们需要添加一个 weight 字段,即使它始终初始化为 1,因此可以在 compareTo 方法中忽略权重。

因此,在我的 graph 类中,我调用我的方法 edgeSet ,它返回一组所有边,但它是一个集合,因此它应该只添加唯一的边,但采用下面这 2 条边

Actor a = new Actor("James");
Actor b = new Actor("Dan");
MovieEdge one = new MovieEdge(a, b, 1, "Movie1");
MovieEdge one = new MovieEdge(b, a, 1, "Movie1");

在比较上面的 2 个 MovieEdge 时,我的compareTo 方法应该输出 0,因为这是一个无向图,但是当我在主方法中调用以下内容时

    testGraph.addEdge(A, C, 1, "Movie1");
    testGraph.addEdge(B, C, 1, "Movie1");
    testGraph.addEdge(C, D, 1, "Movie3");
    testGraph.addEdge(D, A, 1, "Movie1");
    testGraph.addEdge(A, D, 1, "Movie1");
    testGraph.addEdge(A, E, 1, "Movie1");
    System.out.println(testGraph.edgeSet());

在我的主要方法中,这是输出

[A 通过电影 1 到 C,A 通过电影 1 到 D,A 通过电影 1 到 E,B 通过电影 1 到 C,C 通过电影 1 到 A,E 通过电影 1 到 A,C 通过电影 3 到 D]

注意集合如何显示两者 A 通过 Movie1 到 EE 通过 Movie1 到 A 这是不对的

从凌晨 2 点开始(现在是上午 7:43),我一直在更改“compareTo”,但我不明白,我的前 2 个返回 0 的条件应该可以解决这个问题,但由于某种原因,它没有解决。

此外,我还应该指出,当我仅添加一条边(例如 testGraph.addEdge(A, E, 1, "Movie1"); 并调用 System.out.println 时,这很奇怪) (testGraph.edgeSet()); 它打印正确,并且只有 [A via Movie1 to E] 在控制台上打印。

public class MovieEdge implements Comparable {

    private Actor source;
    private Actor destination;
    private int weight;
    private String movieName;

    public MovieEdge(Actor source, Actor destination, int wieght, String movieName){
        this.source = source;
        this.destination = destination;
        this.weight = weight;
        this.movieName = movieName;
    }

    public Actor getSource() {
        return source;
    }

    public Actor getDestination() {
        return destination;
    }

    public int getWeight(){
        return weight;
    }

    public String getMovieName() {
        return movieName;
    }

    public String toString(){
        return source + " via " + movieName + " to " + destination ;
    }

    @Override
    public int compareTo(Object o) {
        MovieEdge a = (MovieEdge)o;
        if(this.movieName.equals(a.movieName)){
            if(this.source.getName().equals(a.source.getName()) && this.destination.getName().equals(a.destination.getName())){
                return 0;
            }
            else if(this.source.getName().equals(a.destination.getName()) && this.destination.getName().equals(a.source.getName())){
                return 0;
            }
            else if(this.destination.compareTo(a.destination) != 0 || this.source.compareTo(a.source) !=0 ){
                return 1;
            }
            return 0;
        }
        if(this.movieName.compareTo(a.movieName) < 0){
            return -1;
        }else if(this.movieName.compareTo(a.movieName) > 0){
            return 1;
        }


        return -1;
    }

}

我的edgeSet方法

public Set<MovieEdge> edgeSet() {
    Set<MovieEdge> values = new TreeSet<MovieEdge>();

    for (TreeSet<MovieEdge> value : adjList.values()) {
        for(MovieEdge m : value){
            values.add(m);
        }
    }

    return values;
}

adjList.values() 只是每个 actor 顶点的 MovieEdge 类型的每个 TreeSet

我的图表通过了我所有讲师的 JUNIT 测试,所以我在这项作业中获得了 A,但这个错误是个人的事情,我必须知道这是错误的。这让我发疯。谢谢。

我更新了 MovieEdge 类的代码,但仍然无法正常工作(给我带来了与上面相同的问题)

`@Override 
public int hashCode(){
    return source.getName().hashCode() + destination.getName().hashCode();
}

@Override
public boolean equals(Object obj){
    MovieEdge a = (MovieEdge)obj;
    if((source.getName().equals(a.source.getName())) && (destination.getName().equals(a.destination.getName()))){
        return true;
    }
    if((source.getName().equals(a.destination.getName())) && (destination.getName().equals(a.source.getName()))){
        return true;
    }
    return false;
}

@Override
public int compareTo(Object o) {
    MovieEdge a = (MovieEdge)o;

    if(movieName.equals(a.movieName)){
        if(equals(a))
            return 0;
        else if(source.getName().compareTo(a.source.getName()) < 0)
            return -1;
        else
            return 1;
    }else if(movieName.compareTo(a.movieName) < 0)
        return -1;

    return 1;
}    `

最佳答案

Lumnitz提供的答案是正确的,我只是想补充以下几点:

Set 通过使用 equals(Object obj) 方法验证对象相等性来消除重复项,您没有为 MovieEdge 类重写该方法。

基本上,您需要了解以下几点:

(1) 覆盖 equals()hashcode() (来自 java.lang.Object)用于检查对象相等性 (您的情况是这样的,即您想通过使用 moviename 等检查某些条件来消除两个 MovieEdge 对象。)

public boolean equals(Object obj) : Indicates whether some other object is "equal to" this one.

(2) 覆盖 compareTo(Object o) (来自 java.lang.Comparable)对对象进行排序(升序/降序)

public interface Comparable : This interface imposes a total ordering on the objects of each class that implements it

关于java - 为什么此类的compareTo 方法没有将边<A,B> 和<B,A> 返回为同一事物?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40677603/

相关文章:

java - 如何从文本文件中获取值

graph - 将本体转换为图形

R图密度平滑时间序列

c++ - 修改 Boost::Graph 中的顶点属性

java - 使用 ExtlibX 访问 MSSQL 表单 Xpages 时出错 - 不支持驱动程序或 JVM

java - 为什么列表中的元素数称为 "size"而数组的长度称为 "length"?

java - JPA Criteria 查询在不同级别上具有多个 IN

algorithm - 创建从根连接的有向图所需的最小边数

java - 循环图

java - 检查 Java 库与 GraalVM 的兼容性