java - Unique Java TreeSet 的可比点

有一个非常简单的 Java 代码示例:

import java.util.*;

class Point implements Comparable<Point>{
  
   float x, y;
   
   Point(float x_, float y_) { x = x_; y = y_; }
   
   int compareTo(Point p_) { println(dist(x, y, p_.x, p_.y)); return dist(x, y, p_.x, p_.y) < 1E-4 ? -1 : 1; }  
    
   float dist(float x0_, float y0_, float x1_, float y1_) { return sqrt(pow(x1_ - x0_, 2) + pow(y1_ - y0_, 2)); }
  
}

public static void main(String[] args){

   TreeSet<Point> tp = new TreeSet<Point>();
   
   tp.add(new Point(0.125, 0.5));
   tp.add(new Point(0.-125, 0.25));
   tp.add(new Point(0.15, -0.75));
   tp.add(new Point(0.125, 0.5));
   
   System.out.println(tp);

}

而且我认为每个点都是 unique,同时进行距离检查,如果它低于 epsilon 代码应该删除重复项。

但是,尽管它是第一个条目的副本,但保留第四个条目是行不通的。

我的目的是获得一组 unique 点 (vectors)。

回答1

之所以如此,是因为 Set 接口是根据 equals 操作定义的,但是 TreeSet 实例使用其 compareTo(或 compare)方法执行所有元素比较,因此该方法认为相等的两个元素是,从集合的角度来看,相等。一个集合的行为是明确定义的,即使它的顺序与equals不一致;它只是不遵守 Set 接口的一般约定。

https://docs.oracle.com/javase/7/docs/api/java/util/TreeSet.html

换句话说,TreeSet类不通过equals方法保持其元素的唯一性,而是通过类实现的compareTo方法,如果类实现了Comparable,或者通过compareTo的给定的 Comparator

正如其他人在评论中指出的那样,如果您想通过坐标保持 Point 之间的唯一性,您应该重写 equalshashCode 方法,就像 https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode() 声明并使用 HashSet 到 store 你的 Point

在下面的代码片段中,我通过实现 equalshashCodetoString 方法更新了您的类,以显示如何只打印三个元素而不是四个元素。

public class Point implements Comparable<Point> {

    double x, y;

    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }

    // ... your implementation ...

    @Override
    public boolean equals(Object obj) {
        if (obj == null) return false;
        if (obj == this) return true;
        if (obj.getClass() != getClass()) return false;
        Point other = (Point) obj;
        return x == other.x && y == other.y;
    }

    @Override
    public int hashCode() {
        return Objects.hash(x, y);
    }

    @Override
    public String toString() {
        return String.format("(%g;%g)", x, y);
    }

    public static void main(String[] args) {
        HashSet<Point> tp = new HashSet<>();

        tp.add(new Point(0.125, 0.5));
        tp.add(new Point(0. - 125, 0.25));
        tp.add(new Point(0.15, -0.75));
        tp.add(new Point(0.125, 0.5));
        
        System.out.println(tp);
    }
}

相似文章

随机推荐

最新文章