#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