这里(下面)是我的MovieEdge
班级;没什么特别的,它指向2个Actor
个对象,它们是这个边缘的顶点。此外,这是一个未加权和无向图,但我们需要添加weight
字段,即使它始终初始化为1,因此可以在compareTo
方法中忽略权重。
所以在我的graph
课程中,我调用我的方法edgeSet
,该方法返回一组所有边但是它是一个集合,所以它应该只添加唯一的边缘但是取下面的这两个边缘
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个MovieEdges时,我的compareTo方法应输出0,因为这是一个无向图,但是当我在main方法中调用以下内容时
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());
在我的main方法中,这是输出
[A via Movie1 to C, A via Movie1 to D, A via Movie1 to E, B via Movie1 to C, C via Movie1 to A, E via Movie1 to A, C via Movie3 to D]
注意集合如何显示
A via Movie1 to E
和E via Movie1 to A
那是不对的
我从凌晨2点开始改变我的'compareTo'(现在是早上7:43),但我不明白,我的前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顶点
我的图表通过了我的所有教练JUNIT测试,所以我得到了这个任务的A,但这个bug是个人的事情,我必须知道WTF是错的。这让我疯了。谢谢。
我更新了,但仍然没有工作(给我同样的问题)上面的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;
} `
答案 0 :(得分:1)
基本上,您的代码中有两个错误:
首先,实现Comparable
,但不要覆盖equals()
方法。
来自Comparable documentation
强烈建议(尽管不要求)自然 排序与平等一致。这是因为排序集 没有显式比较器的(和排序的地图)表现得“奇怪” 它们与自然顺序的元素(或键)一起使用 与equals不一致。特别是,这样的排序集(或排序的 map)违反了定义的集合(或映射)的一般合同 就平等方法而言。
如果movieName
相等而不是source
和destination
,则您的Comparable会有一种奇怪的行为,因为它始终会返回1
。这打破了compareTo contract:
(x.compareTo(y)&gt; 0&amp; y.compareTo(z)&gt; 0)表示x.compareTo(z)&gt; 0
这会导致TreeSet
无法正常工作,因此您的边缘会被添加两次。
编辑:据我所知,compareTo
方法没有简单的实现。因此,我建议使用HashSet
方便的hashCode
和equals
方法。 STH。像这样:
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + Objects.hashCode(movieName);
result *= prime;
// Only add, because order independent
result += Objects.hashCode(destination);
result += Objects.hashCode(source);
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MovieEdge other = (MovieEdge)obj;
if (Objects.equals(movieName, other.movieName))
{
if (Objects.equals(source, other.source)
&& Objects.equals(destination, other.destination))
{
return true;
}
if (Objects.equals(source, other.destination)
&& Objects.equals(destination, other.source))
{
return true;
}
}
return false;
}
答案 1 :(得分:1)
Lumnitz提供的答案是正确的,我只想补充以下几点:
Set
通过使用equals(Object obj)
方法验证对象相等性来消除重复项,您没有覆盖MovieEdge
类。
基本上,您需要了解以下几点:
(1)覆盖equals()
和hashcode()
(来自java.lang.Object
)以检查对象是否相等(您的情况就是这样,即您想要消除两个{ {1}}使用MovieEdge
等检查某些条件的对象。)
public boolean equals(Object obj):指示是否有其他对象 是“等于”这个。
(2)覆盖moviename
(来自compareTo(Object o)
)进行排序(升序/降序)对象
public interface Comparable:此接口强加总排序 关于实现它的每个类的对象