【问题标题】:duplicate children added error for a class that implements hashCode()实现 hashCode() 的类的重复子项添加错误
【发布时间】:2022-02-02 23:23:19
【问题描述】:

我有一个扩展 Circle 的 Point 类。我这样做是为了添加 equals 和 hashCode 方法,以便我可以将实例添加到 Set 中而不会在集合中重复。

我遇到的问题是,当我尝试将具有相同坐标的 2 个点添加到窗格时,我收到重复子项的错误。我对我的代码进行了一些调查,发现它与 hashCode 相关。如果我在 Point 类中注释掉 hasCode 方法,它就可以工作。

我需要能够将所有点添加到窗格中,但只能将不重复的点添加到集合中。

这里是代码。

package my.convexHull;

import java.util.Objects;
import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

/**
 *
 * @author sgordon
 */
public class ConvexHull extends Application {

    final static double RADIUS = 3;
    ObservableList<Node> points;

    @Override
    public void start(Stage stage) throws Exception {
        // Create pane for the piints
        Pane pointsPane = new Pane();
        points = pointsPane.getChildren();

        double p[][] = {
            {30.0, 248.0},
            {114.0, 215.0},
            {114.0, 215.0},
            {114.0, 215.0}
        };
        points.clear();
        for (int i = 0; i < p.length; i++) {
            points.add(new Point(p[i][0], p[i][1], RADIUS));
        }

        Pane linePane = new Pane();
        Pane convexHull = new StackPane(pointsPane, linePane);

        BorderPane root = new BorderPane();

        //Creating a scene object 
        Scene scene = new Scene(root, 430, 330);
        //Setting title to the Stage 
        stage.setTitle("Convex Hull");

        //Adding scene to the stage 
        stage.setScene(scene);

        //Displaying the contents of the stage 
        stage.show();

        root.setCenter(convexHull);
    }

    public static void main(String[] args) {
        Application.launch(args);
    }

    class Point extends Circle {

        public Point() {
            super();
        }

        public Point(double x, double y, double radius) {
            super(x, y, radius);
        }

        @Override
        public int hashCode() {
            return Objects.hash(getCenterX(), getCenterY());
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (!(obj instanceof Point)) {
                return false;
            }

            return getCenterX() == ((Point) obj).getCenterX() && getCenterY() == ((Point) obj).getCenterY();
        }
    }
}

【问题讨论】:

  • 在没有看到整个应用程序的情况下,我认为对正在管理的数据(点集)和该数据在 UI 中的表示使用相同的类是错误的。我会考虑从Point 中删除equals/hashCode,并创建一个管理点标识的新类(比如PointData)。 Point 可以将 PointData 作为构造函数参数。 (话虽如此,我不清楚为什么你的显示应该包括你从你的集合中丢弃的点)
  • 您的粘贴只是将点添加到列表中。 hashCode 并不意味着“它神奇地重复数据删除!” - 你必须把它们放在例如一个不允许重复的 HashSet。
  • @rzwitserloot 这是我的应用程序的准系统版本。我稍后在我的应用程序中将其添加到 TreeSet。我只是想表明它不会让我在窗格中添加重复点。我正在尝试做的是一个 ConvexHull ,因此显示了点,但只有少量点可以创建凸面。
  • @tgdavies 我已经有一个双数组,它们是我正在创建 Point 类的点,专门用于将它们添加到窗格中。
  • 您可以从 Point 中删除 hashCode 和 equals,然后在 TreeSet 中使用自定义比较器。

标签: java observablecollection javafx-11


【解决方案1】:

啊,TreeSet。看,这就是为什么您需要粘贴自包含示例的原因 - 代码本身会显示错误。

TreeSet 完全不使用哈希码

TreeSet 仅使用compare 功能。那个明显坏了。修复它以保持一致,您的问题就会消失。

【讨论】:

    猜你喜欢
    • 2021-09-14
    • 2013-01-16
    • 2013-08-06
    • 1970-01-01
    • 1970-01-01
    • 2011-07-23
    • 2021-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多