Java 树集忽略值
我试图创建一个类,该类被赋予一对字符串&告诉一个比另一个“大”,然后保持所有已知字符串的运行顺序 为此,我保留了一个Java 树集忽略值,java,sorting,treeset,Java,Sorting,Treeset,我试图创建一个类,该类被赋予一对字符串&告诉一个比另一个“大”,然后保持所有已知字符串的运行顺序 为此,我保留了一个映射,该映射将给定的字符串映射到它大于的所有值,然后我创建了一个树集,带有一个比较器,该比较器使用该数据来比较两个字符串 这是我的班级: public class StringSorter { private Map<String, Set<String>> greaterThan = new HashMap<>(); priv
映射
,该映射将给定的字符串
映射到它大于的所有值,然后我创建了一个树集
,带有一个比较器,该比较器使用该数据来比较两个字符串
这是我的班级:
public class StringSorter {
private Map<String, Set<String>> greaterThan = new HashMap<>();
private SortedSet<String> order;
public StringSorter() {
order = new TreeSet<>((o1, o2) -> {
if (greaterThan.getOrDefault(o1, Collections.emptySet()).contains(o2))
return 1;
else if (greaterThan.getOrDefault(o2, Collections.emptySet()).contains(o1))
return -1;
return 0;
});
}
public void addRule(String bigger, String smaller) {
if (!greaterThan.containsKey(bigger))
greaterThan.put(bigger, new HashSet<>());
greaterThan.get(bigger).add(smaller);
order.add(bigger);
order.add(smaller);
}
public SortedSet<String> getOrder() {
return order;
}
}
输出:
[two, one]
字符串
three
和three
发生了什么?问题在于集合集合保持唯一值。
调试完比较器后,您将看到“三”被评估为等于“一”,因此禁止将其添加到集合中
考虑这一修改:
public StringSorter() {
order = new TreeSet<>((o1, o2) -> {
if (greaterThan.getOrDefault(o1, Collections.emptySet()).contains(o2))
return 1;
else if (greaterThan.getOrDefault(o2, Collections.emptySet()).contains(o1))
return -1;
else if(o1.equals(o2)) return 0;
else return -1; //or 1, or o1.compareTo(o2)
});
}
[编辑]
我将考虑将规则的内部表示改变为以稀疏邻接矩阵表示的面向自定义树数据结构。
< P>您可以通过添加这行到您的比较器来回答这个问题。System.out.printf("(%s, %s)%n", o1, o2);
正如您将看到的,无法保证相邻值被传递到比较器。当o1
为“三”且o2
为“一”时,比较返回到零,这告诉树集这两个值相等,显然它不会添加一个它认为等于集合中已有值的值
您需要使对的遍历比的遍历更具传递性。我很确定它需要递归:
private boolean isGreater(String o1,
String o2,
Set<String> keysTried) {
Set<String> greaterSet = greaterThan.get(o1);
if (greaterSet == null) {
return false;
}
if (greaterSet.contains(o2)) {
return true;
}
for (String g : greaterSet) {
if (keysTried.add(g) && isGreater(g, o2, keysTried)) {
return true;
}
}
return false;
}
public StringSorter() {
order = new TreeSet<>((o1, o2) -> {
if (isGreater(o1, o2, new HashSet<>())) {
return 1;
} else if (isGreater(o2, o1, new HashSet<>())) {
return -1;
} else {
return 0;
}
});
}
private boolean更大(字符串o1,
弦o2,
设置键(已尝试){
Set greaterSet=greaterThan.get(o1);
if(greaterSet==null){
返回false;
}
if(更大的含氧量){
返回true;
}
for(字符串g:greaterSet){
如果(按键尝试。添加(g)和大于(g,o2,按键尝试)){
返回true;
}
}
返回false;
}
公共分拣机(){
订单=新树集((o1,o2)->{
if(更大(o1,o2,新哈希集()){
返回1;
}else if(更大(o2,o1,新HashSet()){
返回-1;
}否则{
返回0;
}
});
}
keystread
的目的是防止无限递归。(理论上,如果greaterThan是一个有向图,那么这种情况无论如何都不会发生。)这种方法适用于这种特殊情况,但绝大多数情况下不适用于一般情况。Java的更高版本可以自由更改排序算法,并传递“一”、“三”而不是“三”、“一”。事实上,任何不同的数据集都可能以不同的顺序传递元素。盲目返回-1不会导致正确的行为。@VGR正如我所说,在这一点上,比较是不相关的,我们不能说“一”或“三”是更大的,因为它们之间没有逻辑联系。因此,任何行为都是正确的,包括返回1、-1或o1。与(o2)相比,严格来说,它不需要递归,只是使它更易于编写和读取。
System.out.printf("(%s, %s)%n", o1, o2);
private boolean isGreater(String o1,
String o2,
Set<String> keysTried) {
Set<String> greaterSet = greaterThan.get(o1);
if (greaterSet == null) {
return false;
}
if (greaterSet.contains(o2)) {
return true;
}
for (String g : greaterSet) {
if (keysTried.add(g) && isGreater(g, o2, keysTried)) {
return true;
}
}
return false;
}
public StringSorter() {
order = new TreeSet<>((o1, o2) -> {
if (isGreater(o1, o2, new HashSet<>())) {
return 1;
} else if (isGreater(o2, o1, new HashSet<>())) {
return -1;
} else {
return 0;
}
});
}