2011-01-06 83 views
2

有一个SortedSet,我需要基于列表中特定元素的特定记录片段。Groovy(或Java)中排序集的子集

示例: 在下面的代码,challengeDTO.members是SortedSet的(TreeSet中实现)

我知道一个构件

def memberRank = challengeDTO.members.findIndexOf { it.member.id == membership?.id} + 1 

的位置如果memberRank为66,我想要得到一小部分成员60至70排名。

challengeDTO.members [60..69]将无法工作,因为它是一组

想法?建议?

成员实现:

class ChallengeMemberDTO implements Comparable<ChallengeMemberDTO> { 

    ChallengeMember member 
    Integer total 
    String name 
    String teamName 

    int compareTo(ChallengeMemberDTO t) { 
    if (total == t.total) { // the sortedset will remove duplicates based on same total, which is not desireable 
     return name.compareTo(t.name) 
    } 
    else { 
     return t.total.compareTo(total) 
    } 
    } 
} 

回答

3

尝试:

(challengeDTO.members as List)[60..69] 

在此基础上,Groovy as List类型转换创建了一个ArrayList的实例,并调用addAll,传递您的SortedSet。按照java.util.List JavaDoc addAll“将指定集合中的所有元素附加到此列表的末尾,按照它们由指定集合的​​迭代器返回的顺序”。在JavaDoc的java.util.SortedSet中,它声明“集合的迭代器将按升序元素顺序遍历集合。”

因此,列表的顺序将与SortedSet的顺序相匹配。

如果你有兴趣,你可以在Groovy的源代码,看看方法:

org.codehaus.groovy.runtime.DefaultGroovyMethods.asList(Collection<T> self)

编辑:

为求完整,在Java中你可以请执行下列操作。这正是Groovy的代码在幕后上面做:

SortedSet<ChallendMemberDTO> memberSet = challengeDTO.getMembers(); 
List<ChallengeMemberDTO> membersPage = new ArrayList<ChallengeMemberDTO>(memberSet).subList(60, 70); 
1

嗯,这一点,你必须了解的SortedSet是如何工作的。

SortedSet的方法中可以使用的项目都是这些项目的compare()方法或项目的compareTo()方法将返回一个数值。

因此,如果compareTo()实现您的会员类的可以让你的成员比作一个号码,你可以使用简单的

challengeDTO.members.subSet(60, 70) 
+2

*如果的compareTo()实现您的会员类的可以让你的成员比作一个数量*我会强烈建议不要说,因为这将创建一个单向比较器。这违反了`sgn(x.compareTo(y))`必须等于`-sgn(y。compareTo(x))`(Effective Java 2nd Ed,Item 12) – 2011-01-06 13:24:39

+0

猜猜是什么?我已经知道这一点。但是,有些情况下这是一个非常有效的捷径,因为完整的代码需要创建具有所需id(但不包含其他内容)的成员,然后期望默认成员compareTo方法正确行为。这就是为什么我精确地说,为了以“干净”的方式处理这个问题,我们也可以重写这个SortedSet Comparator字段。 – Riduidel 2011-01-06 13:33:32

+2

我同意肖恩帕特里克弗洛伊德认为,即使为了效率而打破“比较器”合同也是一个坏主意(特别是因为[过早优化是万恶之源](http://en.wikiquote.org/)维基/ Donald_Knuth]))。另外,将该类与数字进行比较是视图代码的人工制品,它不应该进入域。它可能比简单的`new ArrayList (challengeDTO.members).subList(60,70)`更有效率 - 我不知道(它可能主要取决于`compareTo`的实现)。如果速度太慢,让剖析器决定。 – 2011-01-06 23:08:11

1

SortedSet<E>为此具有的headSet(E)tailSet(E)subSet(E, E)方法。

只是通过在与价值观正确比较变量你想要的:

Sample类:

public class Member implements Comparable<Member>{ 

    public Member(final int value){ this.value = value; } 
    private final int value; 
    public int getValue(){ return value; } 

    @Override public int hashCode(){ return 31 * value; } 

    @Override public boolean equals(final Object obj){ 
     return obj instanceof Member && ((Member) obj).value == value; 
    } 

    @Override public String toString(){ "[Member, value="+value+"]"; } 

    @Override public int compareTo(final Member o){ 
     return Integer.valueOf(value).compareTo(Integer.valueOf(o.value)); 
    } 
} 

示例代码:

public static void main(final String[] args){ 
    final SortedSet<Member> set = new TreeSet<Member>(); 
    for(int i = 0; i < 10; i++){ 
     set.add(new Member(i)); 
    } 
    System.out.println("TailSet(7): " + set.tailSet(new Member(7))); 
    System.out.println("HeadSet(3): " + set.headSet(new Member(3))); 
    System.out.println("SubSet(6, 8): " + 
          set.subSet(new Member(6), new Member(8))); 
} 

输出:

TailSet(7):[[Member,value = 7],[Member,v (3):[[成员,值= 0],[成员,值= 1],[成员,值= 2]]
子集(6),[成员,值= 9]]
,8):[[会员,值= 6],[会员,值= 7]]


及这里的构建切片(使用NavigableSet接口,这是SortedSet的超集的方法并且还通过TreeSet实现):

public static <K> List<K> slice(final NavigableSet<K> set, 
    final K reference, 
    final int elementsBefore, 
    final int elementsAfter){ 
    final List<K> list = new ArrayList<K>(); 
    final Iterator<K> headIterator = 
     set.headSet(reference, false).descendingIterator(); 
    int headCt = 0; 
    while(headIterator.hasNext() && headCt++ < elementsBefore){ 
     list.add(0, headIterator.next()); 
    } 
    list.add(reference); 
    final Iterator<K> tailIterator = 
     set.tailSet(reference, false).iterator(); 
    int tailCt = 0; 
    while(tailIterator.hasNext() && tailCt++ < elementsAfter){ 
     list.add(tailIterator.next()); 
    } 

    return list; 
} 

用法:

final NavigableSet<Member> set = new TreeSet<Member>(); 
for(int i = 0; i < 100; i++){ 
    set.add(new Member(i)); 
} 
System.out.println(slice(set, new Member(67), 2, 2)); 
System.out.println(slice(set, new Member(2), 25, 2)); 

输出:

[[会员,值= 65],[会员,值= 66],[会员,值= 67],[会员,值= 68],[会员,值= 69]]
[[Member,value = 0],[Member,value = 1],[Member,value = 2],[Member,value = 3],[Member,value = 4]]