Подмножество сортированного набора в Groovy (или Java) - PullRequest
2 голосов
/ 06 января 2011

У меня есть SortedSet, где мне нужен определенный фрагмент записей на основе определенного элемента в списке.

Пример: В приведенном ниже коде 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 ]

3 голосов
/ 06 января 2011

Попробуйте:

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

Под прикрытием преобразование типа Groovy as List создает экземпляр ArrayList и вызывает addAll, передавая ваш SortedSet. Согласно java.util.List JavaDoc addAll "добавляет все элементы в указанной коллекции в конец этого списка в порядке, в котором они возвращаются итератором указанной коллекции". В java.util.SortedSet JavaDoc говорится, что «итератор набора будет проходить по множеству в порядке возрастания элементов».

Таким образом, порядок списка будет соответствовать порядку SortedSet.

Если вам интересно, вы можете взглянуть на метод в исходном коде Groovy:

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

EDIT:

Ради полноты в Java вы можете сделать следующее. Это то, что Groovy-код выше делает под прикрытием:

SortedSet<ChallendMemberDTO> memberSet = challengeDTO.getMembers();
List<ChallengeMemberDTO> membersPage = new ArrayList<ChallengeMemberDTO>(memberSet).subList(60, 70);
1 голос
/ 06 января 2011

SortedSet<E> имеет методы headSet(E), tailSet(E) и subSet(E, E) для этой цели.

Просто передайте переменную, которая правильно сравнивается со значениями, которые вы хотите:

Образец класса:

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, value = 8], [Member, value = 9]]
HeadSet (3): [[Member, value = 0], [Member, value = 1], [Member, value = 2]]
Подсеть (6, 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]]

1 голос
/ 06 января 2011

Ну, для этого вы должны понять, как работает SortedSet.

Элементы, которые можно использовать в методах SortedSet, - это все те, для которых метод compare() компаратора или метод compareTo() элементов вернут числовое значение.

Как следствие, если реализация compareTo() вашего класса-члена позволяет вам сравнивать членов с числом, вы можете просто использовать

challengeDTO.members.subSet(60, 70)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...