我有一组具有名称(a)和依赖(b)的对象。我想以一种解决所有先前依赖关系的方式对对象进行排序。所以我有这个代码:
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
public class Foo {
static class TestOrder implements Comparable<TestOrder> {
private final String a;
private final Set<String> b;
public TestOrder(String a, Set<String> b) {
this.a = a;
this.b = b;
}
public int compareTo(TestOrder o) {
if (o.b.contains(a))
return -1;
else
return 1;
}
@Override
public int hashCode() {
return a.hashCode();
}
@Override
public boolean equals(Object obj) {
return a.equals(obj);
}
public String toString() {
return a + " - " + b.toString();
}
}
public static void main(String[] args) {
Set<TestOrder> tos = new TreeSet<>();
tos.add(new Foo.TestOrder("a", new HashSet<String>() {{
add("b");
add("c");
}}));
tos.add(new Foo.TestOrder("e", new HashSet<String>() {{
add("a");
}}));
tos.add(new Foo.TestOrder("b", new HashSet<String>() {{
add("d");
add("c");
}}));
tos.add(new Foo.TestOrder("c", new HashSet<String>() {{ }}));
tos.add(new Foo.TestOrder("d", new HashSet<String>() {{ }}));
for (TestOrder to : tos) {
System.out.println(to.toString());
}
}
}
导致:
c - []
b - [d, c]
a - [b, c]
e - [a]
d - []
但是 - 由于b取决于d - 预期结果将是:
c - []
d - []
b - [d, c]
a - [b, c]
e - [a]
我错过了什么?
答案 0 :(得分:2)
你遗漏了几件事(以较难修复的顺序,从较简单的顺序开始):
您可以在返回this
之前检查o
对1
的依赖关系,并使用a.compareTo(o.a)
来打破平局,从而相对轻松地修复前两个。
public int compareTo(TestOrder o) {
if (o.b.contains(a))
return -1;
else if (b.contains(o.a))
return 1;
else
return a.compareTo(o.a);
}
第三个可以通过切换到一个数组来修复,并且只在完成所有插入后才对其进行排序。
然而,最后一个非常糟糕:为了解决这个问题,每个项目都需要知道集合的其余部分。我没有看到一个很好的方法,所以我建议使用传统的topological sorting algorithm来命令你的依赖,而不是试图在Java集合框架中解决这个问题。
答案 1 :(得分:0)
您的比较方法在空集和不包含字符串“a”的集之间没有区别。这种比较方法
public int compareTo(TestOrder o) {
if (o.b.contains(a)) {
return -1;
} else {
if (o.b.isEmpty() && b.isEmpty()) {
return a.compareTo(o.a);
} else
if (o.b.isEmpty() || b.isEmpty()) {
return b.isEmpty() ? -1 : 1;
} else {
return 1;
}
}
}
将给出结果
c - []
d - []
b - [d, c]
a - [b, c]
e - [a]
答案 2 :(得分:0)
如果有人感兴趣,这就是它的工作方式 - 最后(感谢dasblinkenlight):
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* @author Krusty
*/
public class Foo {
static class TestOrder implements Comparable<TestOrder> {
private final String a;
private final Set<String> b;
public TestOrder(String a, Set<String> b) {
this.a = a;
this.b = b;
}
public int compareTo(TestOrder o) {
if (o.b.contains(a)) {
return -1;
} else {
if (o.b.isEmpty() && b.isEmpty()) {
return a.compareTo(o.a);
} else
if (o.b.isEmpty() || b.isEmpty()) {
return b.isEmpty() ? -1 : 1;
} else {
return 1;
}
}
}
@Override
public int hashCode() {
return a.hashCode();
}
@Override
public boolean equals(Object obj) {
return a.equals(obj);
}
public String toString() {
return a + " - " + b.toString();
}
}
public static void main(String[] args) {
Set<TestOrder> tos = new TreeSet<>();
tos.add(new Foo.TestOrder("a", new HashSet<String>() {{
add("b");
add("c");
}}));
tos.add(new Foo.TestOrder("e", new HashSet<String>() {{
add("a");
}}));
// Cycle
/*
tos.add(new Foo.TestOrder("a", new HashSet<String>() {{
add("e");
}}));
*/
tos.add(new Foo.TestOrder("b", new HashSet<String>() {{
add("d");
add("c");
}}));
tos.add(new Foo.TestOrder("c", new HashSet<String>() {{ }}));
tos.add(new Foo.TestOrder("d", new HashSet<String>() {{ }}));
/*
for (TestOrder to : tos) {
System.out.println(to.toString());
}*/
for (TestOrder to : sort(tos)) {
System.out.println(to.toString());
}
}
public static Set<TestOrder> sort(Set<TestOrder> tos) {
Set<TestOrder> sorted = new LinkedHashSet<>();
Set<String> cache = new LinkedHashSet<>();
Set<TestOrder> cycles = new LinkedHashSet<>();
Set<String> cycache = new LinkedHashSet<>();
Iterator<TestOrder> it;
while ((it = tos.iterator()).hasNext()) {
TestOrder to = it.next();
if (to.b.isEmpty()) {
sorted.add(to);
cache.add(to.a);
it.remove();
} else if (cache.containsAll(to.b)) {
sorted.add(to);
cache.add(to.a);
it.remove();
} else if (cycache.containsAll(to.b)) {
cycles.add(to);
cycache.add(to.a);
it.remove();
} else {
cycles.add(to);
cycache.add(to.a);
it.remove();
}
}
System.err.println("cycles");
for (TestOrder to : cycles) {
System.err.println(to.toString());
}
return sorted;
}
}