어떻게 제대로 자바 트리에 대한 등호 (), 해시 코드 ()를 구현하는 방법?

FreeOnGoo :

나는 트리 구조를하고 난 동일 방법을 재정의해야 / 해시 코드를 내가 단위 테스트에서 예상되는 결과의 수표를 사용하기 때문에.

트리 형 구조의 문제점은 반복적으로 서로를 참조하는 것이 있습니다. 특히, 어린이와 그 반대에 대한 부모.

모든 필드는 방법에서 사용하는 경우 같음 / 해시 코드, 다음 루프가있을 것입니다. 문제는 제대로 계약을 위반하지 않기 위해 다음 재정의하는 방법입니다.

나는 그것을 구현하는 방법의 예를 제공 할 것입니다.

public class App {
    public static void main(String[] args) {
        Book book1 = new Book(1L, "The catcher in the rye");
        Book book2 = new Book(2L, "Rich Dad Poor Dad");

        BookTree bookTree1 = new BookTree(book1);
        BookTree bookTreeChild1 = new BookTree(book2);
        bookTree1.addChild(bookTreeChild1);

        BookTree bookTree2 = new BookTree(book1);
        BookTree bookTreeChild2 = new BookTree(book2);
        bookTree2.addChild(bookTreeChild2);

        if (!bookTree1.equals(bookTree2)) {
            throw new RuntimeException("Invalid override equals");
        }
    }
}

class Book {
    private Long id;
    private String name;

    public Book(Long id, String name) {
        this.id = id;
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object object) {
        if (this == object) return true;
        if (object == null || getClass() != object.getClass()) return false;
        Book book = (Book) object;
        return Objects.equals(id, book.id) &&
                Objects.equals(name, book.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name);
    }
}

class Tree<T> {
    private List<Tree<T>> children = new ArrayList<>();
    private Tree<T> parent = null;
    private T data;

    public Tree(T data) {
        this.data = data;
    }

    public Tree(T data, Tree<T> parent) {
        this.data = data;
        parent.addChild(this);
    }

    public List<Tree<T>> getChildren() {
        return children;
    }

    public void addChild(Tree<T> child) {
        child.setParent(this);
        this.children.add(child);
    }

    public void addChild(T data) {
        Tree<T> newChild = new Tree<>(data);
        this.addChild(newChild);
    }

    public void removeChildren() {
        this.children = new ArrayList<>();
    }

    public void addChildren(List<Tree<T>> children) {
        for(Tree<T> t : children) {
            t.setParent(this);
        }
        this.children.addAll(children);
    }

    private void setParent(Tree<T> parent) {
        this.parent = parent;
    }

    public Tree<T> getParent() {
        return parent;
    }

    public T getData() {
        return this.data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public boolean isRoot() {
        return (this.parent == null);
    }

    public boolean isLeaf() {
        return this.children.size() == 0;
    }

    public void removeParent() {
        this.parent = null;
    }

    @Override
    public boolean equals(Object object) {
        if (this == object) return true;
        if (object == null || getClass() != object.getClass()) return false;
        Tree<?> tree = (Tree<?>) object;
        return Objects.equals(children, tree.children) &&
                Objects.equals(data, tree.data);
    }

    @Override
    public int hashCode() {
        return Objects.hash(children, data);
    }
}

class BookTree extends Tree<Book> {

    public BookTree(Book data) {
        super(data);
    }

    public BookTree(Book data, Tree<Book> parent) {
        super(data, parent);
    }
}

"데이터"와 "어린이"당신이 내 구현에서 볼 수 있듯이, 나는 단지 두 개의 필드를 사용합니다. 따라서, 내 문제는 내가 제대로 된 방법의 같음 / 해시 코드를 구현 여부? 잘못된 경우, 다음 방법을 보여주십시오.

GhostCat 경례 모니카 C. :

따라서, 내 문제는 내가 제대로 된 방법의 같음 / 해시 코드를 구현 여부?

첫째는 "올바른 무엇인가?" ... 하나는 나무가 구현해야하는 이유를 궁금해 할 수 equals()hashCode()처음이다. 특히 hashCode()까다 롭다 :하면의 HashMap / HashSet의에 대응하는 객체를 저장할 수 있도록하는 방법의 요점은 (주로)이다. 그러나 그것은 큰 붉은 깃발을 제기 : 이러한 클래스 모두 할 수 없습니다 , 그것은 같은 경우 hashCode()시간이 지남에 따라 반환 다른 값. 때마다 당신이 당신의 나무 (노드를 추가 / 제거) 변경 : 그리고 그 코드가 일을 할 것입니다 정확히 hashCode()다른 결과를 줄 것이다.

그래서 우리는 표준 libs와 무엇을 살펴 수 : 우리가 찾을 수 JTree에 두 가지 방법을 구현하지 않습니다 ...! 우리가 방향으로 볼 때 다른 한편으로는, AbstractSet (TreeSet에 대한 기본 클래스이다), 우리는이 두 가지 방법이 구현되는 것을 발견하고 회원을 포함한다. 그래서 두 가지 방법이 유효한 것으로 보인다.

질문에 돌아 오는 : 정말 당신이 얼마나 의존 하려는 작업에이 두 가지 방법을. 이 나무들은 동일한 내용이있을 때 동일 (의미 : 어린이의 순서가 중요 않음)?

긴 이야기를 짧게 : 당신이 모든 것을 보장 할 것으로 가정 데이터가 동일하고, 모든 것을 아이들이 동일하고, 동일한 순서로, 다음 구현이 올 것 같다.

그리고 네, 그 제한 만이 두 속성을 확인하는 많은 이해 : 상위 링크를 포함 할 때, 즉시 파괴 될 수없는 재귀로 얻을.

마지막으로 : 당신은 JUnit을이 질문에 태그. 이 프로덕션 코드를 작성하는 테스트를 고려하는 것이 의미한다. 그리고 이러한 테스트는 귀하의 질문에 대답해야한다. 의미 : 한 가지 방법은 당신이 앉아 있다는 것 정의 이러한 두 가지 방법에 대한 계약을. 그리고 당신은 테스트 케이스의 수를 만들 확인 이 계약의 모든 측면을. 그리고 테스트 케이스 프로덕션 코드가 계약을 충족하는지 여부를 알려줍니다.

나는 여기에서 중요한 점을 생각 : 어떻게 구현 / 경우 우리에게 보편적 인 규칙이없는 equals()hashCode()트리 클래스가. 당신은이 작업을 수행하는 방법을 경우 / 요구 사항으로보고있다. 그럼 당신은 당신이 당신이 주어진 구현이 요구 사항 / 계약을 충족하는지 확인하기 위해 적용 지식에서 테스트를 도출.

추천

출처http://43.154.161.224:23101/article/api/json?id=236315&siteId=1