【发布时间】:2017-08-28 13:13:24
【问题描述】:
我正在寻找一种方法来对一组集合进行排序 - 更具体地说,数据结构需要具有以下属性:
- “外部”和“内部”集合都应该是集合,即包含的集合中不应有重复的元素,也不应有重复的集合。
- 集合应该按照包含集合的长度升序排序,即{{A}, {A, B}, {A, C, F}, {B, D, F}}有效而 {{A, C, F}, {A, B}, {B, D, F}, {A}} 不是。
- 应该可以迭代单个包含的集合以及所有集合。当然,遍历所有集合应该根据它们各自的大小按升序列出它们。
- 如果两个集合的大小相同,则顺序可能是任意的。
我的基本方法是TreeSet<TreeSet<T>>,尽管由于包含的 TreeSets 需要按照自定义行为进行排序,所以我编写了一个包装类(省略了不必要的细节,例如额外的构造函数和方法):
import java.util.TreeSet;
import java.util.Iterator;
import java.util.Collection;
public class WrappedSet< T > implements Comparable< WrappedSet< T >>, Iterable< T > {
protected TreeSet< T > set;
public WrappedSet( Collection< T > collection ) {
set = new TreeSet< T >( collection );
}
public int size() {
return set.size();
}
@Override
public Iterator< T > iterator() {
return set.iterator();
}
@Override
public int compareTo( WrappedSet< T > other ) {
if ( set.equals( other.set )) {
return 0;
}
else {
return ( set.size() >= other.set.size()) ? 1 : -1;
}
}
@Override
public String toString() {
return set.toString();
}
}
为了展示问题,我使用了这个主函数:
public static void main( String[] args ) {
TreeSet< WrappedSet< String >> wsets = new TreeSet< WrappedSet< String >>();
for ( String arg : args ) {
wsets.add( new WrappedSet< String >( new TreeSet< String >( Arrays.asList( arg.split( "," )))));
}
System.out.println( "Input sets: " + Arrays.toString( wsets.toArray()));
}
我明白,如果我的 .equals() 这个类是基于测试各个集合的相等性,我的 "类 [将具有] 与 equals 不一致的自然顺序",如CompareTo documentation 表示它。我也明白这可能是输出(有时)不正确的原因。考虑以下示例:
输入(命令行):A,B,E A,C,F B,D,F A A,B,E
输出:输入集:[[A], [A, B, E], [A, C, F], [B, D, F], [A, B, E]]
如您所见,{A, B, E} 出现了两次,我想这是因为 TreeSet 遍历树以找到具有该值的现有条目,但最终没有找到它,因为顺序元素的数量与它们的实际值无关 - 只有它们的大小。
我怎样才能以一致的方式实现所需的行为?请注意,这不是家庭作业。因此自然欢迎不基于 TreeSet 的解决方案。
【问题讨论】:
-
当你定义一个可比较对象时,你必须确保对于所有集合,
a.compareTo(b)永远不会返回与b.compareTo(a)相同的答案,除非它们相等(两者都必须返回 0) .您的compareTo违反了该规则(反对称)。 -
您在
compareTo()方法中使用了TreeSet.equals()。这不是真的工作...您应该将equals实现到您的班级WrappedSet,并改用它... -
当两个集合大小相等时,您的方法可能会返回 1。据我了解,您仍然没有“比较方法违反其一般合同”的事实!异常可能只是一个幸运的巧合。
-
@UsagiMiyamoto 我已经实现但省略了它。这基本上是我的 compareTo 的第一行,所以老实说,我看不出这会有什么帮助。
-
@M.Prokhorov 那是因为,正如我所说,当集合具有相同大小时,我不关心顺序。对我来说,重要的是它们是否作为集合相等,或者它们是否比其他集合更大或更小。问题是,当两组大小相同时,我不知道我应该做什么,尤其是在这种情况下顺序无关紧要的情况下。