Сравнение набора деревьев не дает желаемого результата

#java #comparable #treeset

#java #сопоставимый #treeset

Вопрос:

Я пытаюсь создать набор всех букв во всех словах в словаре.

Для этого я использую набор деревьев, поскольку мне приходится выполнять множество операций сравнения.

 
public class main {

    public static void main(String[] args) {

        Set<String> lines = new TreeSet<>();
        lines.add("ba");
        DictAwareSolver myGuesser = new DictAwareSolver(lines);
        myGuesser.makeGuess();
    }
}
  

Это мой класс, который работает с набором

 package solver;

import sun.reflect.generics.tree.Tree;

import java.util.*;
import java.lang.System;

public class DictAwareSolver extends HangmanSolver
{

    private Set<String> dict;


    TreeSet<Node> myTree = new TreeSet<>();


    //getters

    public Set<String> getDict() {
        return dict;
    }
    


    // methods

    public DictAwareSolver(Set<String> dictionary) {
        this.dict = dictionary;
        // Implement me!
    } // end of DictAwareSolver()


    @Override
    public void newGame(int[] wordLengths, int maxIncorrectGuesses)
    {
        // Implement me!
    } // end of newGame()


    @Override
    public char makeGuess() {
        Set<String> guessDict = getDict();

        Iterator dictItr = guessDict.iterator();

        while (dictItr.hasNext())
        {
            String word = (String) dictItr.next();

            for (int i = 0; i<word.length(); i  )
            {
                Node temp = new Node(word.charAt(i));
                myTree.add(temp);
            }
        }

        Iterator treeItr = myTree.iterator();

        while (treeItr.hasNext())
        {
            Node n = (Node) treeItr.next();
            System.out.println(n.getLetter()   "-->" n.getFrequency());
        }
        // TODO: This is a placeholder, replace with appropriate return value.
        return '';
    } // end of makeGuess()


    @Override
    public void guessFeedback(char c, Boolean bGuess, ArrayList< ArrayList<Integer> > lPositions)
    {
        // Implement me!
    } // end of guessFeedback()

} // end of class DictAwareSolver

class Node implements Comparable<Node>{
    private char letter;
    private int frequency;

    public Node(char letter)
    {
        this.letter = letter;
        this.frequency = 1;
    }

    public void countIncrementer()
    {
        int newCount = getFrequency() 1;
        setFrequency(newCount);
    }

    // getters

    public char getLetter() {
        return letter;
    }

    public int getFrequency() {
        return frequency;
    }

    // setters


    public void setFrequency(int frequency) {
        this.frequency = frequency;
    }

    @Override
    public int compareTo(Node o) {
        if (getLetter() == o.letter)
        {
            o.countIncrementer();
            return 0;
        }
        else if (getLetter() > o.getLetter())
        {
            return 1;
        }
        else
        {
            return -1;
        }
    }
}
  

Когда я запускаю это, все, что я добавляю 1st, дает количество 2. Поскольку в этом случае вывод

a—> 1 b—> 2

но я ожидаю

a—> 1 b—> 1

Будет действительно полезно, если вы сможете указать, в чем проблема. Из того, что я могу придумать, это должно быть что-то в моем o.countIncrementer(); в моем методе compareTo. Я новичок в Java.

Комментарии:

1. Добро пожаловать в Stack Overflow. В настоящее время вы опубликовали более 125 строк кода. Здорово, что вы предоставили полный пример, но было бы лучше, если бы вы могли свести его к минимальному примеру, который включает только код, необходимый для воспроизведения проблемы … в противном случае вы просите людей просмотреть много кода, чтобы определить, что имеет значение.

2. compareTo() не должно иметь побочных эффектов. Я даже не понимаю, почему вы построили его таким образом.

3. @Milgo можете ли вы объяснить compareTo() , что не должно иметь побочных эффектов

4. Вы увеличиваете частоту узла, с которым сравниваете, внутри compareTo метода . Это побочный эффект этого метода, которого у него не должно быть, среди прочего, потому TreeSet что сортирует свои элементы с помощью этого метода.

5. @AyushRanjan Самым простым решением была бы структура данных, отличная Set<Node> от отслеживания подсчетов. Для Map<Character, Integer> (или Map<Character, Node если вы Node по какой-то причине хотите сохранить тип) была бы одна структура данных, которую вы могли бы использовать для подсчета количества на букву.

Ответ №1:

В коде делается предположение, что TreeSet будет вызываться компаратор только для равного элемента, если он уже существует в наборе, и если он выполняет такое сравнение, он будет делать это только один раз. Однако это не так, как TreeSet это реализовано. Просматривая документацию API для TreeSet , нет никаких гарантий относительно того, как будут выполняться сравнения или с какой частотой. Поскольку это не документированная часть API, авторы TreeSet могут свободно реализовать эту функциональность любым разумным способом, который они пожелают, если он соответствует документированному API. Фактически, им также разрешено изменять способ его реализации между версиями (например, Java 6 и Java 7) или между различными реализациями (например, Oracle против IBM).

Короче говоря, если документация не гарантирует поведение, ваш код не должен полагаться на это поведение.

Чтобы перейти к конкретному поведению, которое вы видите, первый элемент, добавленный в a TreeSet (в версиях Java, которые вы используете), сравнивается с самим собой. Хотя это, возможно, удивительно, это не запрещено API. Для этого может быть или не быть веской причины (я полагаю, что проверка была добавлена в Java 7, чтобы заставить a NullPointerException выбрасываться при null добавлении a в качестве первого элемента в a TreeSet , который запрещает null для этой ошибки). Однако, в конце концов, причина проверки не должна иметь значения для пользователей API, поскольку она не запрещена в API.

 public static void main(String[] args) {
    System.out.printf("Java vendor amp; version: %s %sn", System.getProperty("java.vendor"), Runtime.version());

    TreeSet<Character> set = new TreeSet<>(new LoggingComparator<>());
    set.add('a');
}

private static class LoggingComparator<T extends Comparable<? super T>> implements Comparator<T> {
    @Override
    public int compare(T o1, T o2) {
        System.out.println(o1   " <=> "   o2);
        return o1.compareTo(o2);
    }
}
  
 Java vendor amp; version: Oracle Corporation 11.0.4 10-LTS
a <=> a