Как вернуть N последовательных элементов из Коллекции? - PullRequest
7 голосов
/ 01 апреля 2011

Мне передали коллекцию объектов (в моем случае некоторый класс Contact), и мне нужно вернуть страницу из этой коллекции. Мой код чувствует себя намного дольше, чем нужно. Я скучаю по некоторым библиотекам, которые могли бы выполнять это более элегантно, чем перебирать каждый элемент по одному, как я делаю ниже?

protected Collection<Contact> getPageOfContacts(
  Collection<Contact> contacts, int pageIndex, int pageSize) {
  if (pageIndex < 0 || pageSize <= 0
    || pageSize > contacts.size()) {
    return contacts;
  }
  int firstElement = pageIndex * pageSize;
  int lastElement = (pageIndex + 1) * pageSize - 1;
  Collection<Contact> pagedContacts = new ArrayList<Contact>();
  int index = -1;
  for (Contact contact : contacts) {
    index++;
    if (index < firstElement) {
      continue;
    }
    if (index > lastElement) {
      break;
    }
    pagedContacts.add(contact);
  }
  return pagedContacts;
}

Ответы [ 6 ]

12 голосов
/ 01 апреля 2011

Вы можете использовать Гуава Iterables.partition :

protected <T> Collection<T> getPageOfContacts(
        Collection<T> contacts, int pageIndex, int pageSize) {
    return Lists.newArrayList(
        Iterables.partition(contacts, pageSize)).get(pageIndex);
}

Более сложная версия не создает все страницы для выбора нужной, но останавливается, когда найдена правильная страница.

protected <T> Collection<T> getPageOfContacts(
        Collection<T> contacts, int pageIndex, int pageSize) {
    Iterator<List<T>> partitions = Iterators.partition(contacts.iterator(), pageSize);

    for(int page = 0; page<pageSize && partitions.hasNext(); page++){
        List<T> partition = partitions.next();
        if(page == pageIndex) return partition;
    }
    return Collections. <T> emptyList(); //or fail
}

Обновление:

Спасибо ColinD за то, что:

Iterables.get(Iterables.partition(contacts, pageSize), pageIndex)

- более простая реализация.

6 голосов
/ 01 апреля 2011

Если вы хотите, чтобы данные были разбиты на страницы как List, вы можете легко получить представление подсписка одной страницы, используя Guava :

public <T> List<T> getPage(List<T> list, int pageIndex, int pageSize) {
  return Lists.partition(list, pageSize).get(pageIndex);
}

Это не требует копирования или итерации (использует представления подсписков исходного списка) и обрабатывает последнюю страницу, которая прозрачно содержит менее pageSize элементов.

Для произвольного Iterable или Collection я бы сделал это:

public <T> List<T> getPage(Iterable<T> iterable, int pageIndex, int pageSize) {
  return Iterables.get(Iterables.partition(iterable, pageSize), pageIndex);
}

Предоставив оба этих метода, вы сможете эффективно обрабатывать объекты, которые, как известно, являются списками во время компиляции, и любой другой тип Iterable настолько эффективно, насколько это возможно.

4 голосов
/ 01 апреля 2011

Если вы хотите определенный порядок для ваших элементов, вы должны использовать List, а не collection.Основное различие между List и Collection заключается в том, что List имеет фиксированный порядок элементов.Он также определяет очень удобный метод subList(int start, int end), который создает подсписок, который является псевдонимом исходного списка, содержащего только те элементы, которые вы хотите, без дополнительных затрат на копирование их в новый список.

1 голос
/ 01 апреля 2011

Интерфейс List предоставляет метод subList, который принимает начальный индекс и конечный индекс. См. http://download.oracle.com/javase/6/docs/api/java/util/List.html#subList(int,%20int). Возвращенный подсписок поддерживается исходным списком, поэтому вы, вероятно, захотите сделать что-то вроде

protected Collection<Contact> getPageOfContacts(...) {
    return new ArrayList<Contact>(original.subList(start,end));
}
0 голосов
/ 09 ноября 2016
Iterables.partition(contacts, pageSize).forEachRemaining(paginatedContacts->{/*Operation here*/});
0 голосов
/ 01 апреля 2011
return new ArrayList<Contact>(new ArrayList<Contact>(contacts).subList(firstElement, lastElement));

Примечание: это вернет подсписок эксклюзив lastElement

Примечание 2. Результат копируется в другой список по причинам, указанным Кевином.

...