如何从Collection中返回N个连续元素?

时间:2011-04-01 16:06:45

标签: java collections iteration paging guava

我传递了一个对象集合(在我的情况下是一些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 个答案:

答案 0 :(得分:12)

你可以使用番石榴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)

是一个更简单的实现。

答案 1 :(得分:6)

如果您可以要求将数据分页为List,则可以使用Guava轻松获取单个页面的子列表视图:

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

这不涉及复制或迭代(它使用原始列表的子列表视图)并处理透明地少于pageSize个元素的最终页面。

对于任意IterableCollection,我会这样做:

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

通过提供这两种方法,您将能够有效地处理编译时已知为列表的对象以及任何其他类型的Iterable

答案 2 :(得分:4)

如果您希望为元素定义订单,则应使用List,而不是collectionListCollection之间的基本区别在于List对元素具有固定顺序。它还定义了非常方便的方法subList(int start, int end),该方法创建了一个子列表,该子列表是原始列表的别名,仅包含您想要的元素,而无需将其复制到新列表的开销。

答案 3 :(得分:1)

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));
}

答案 4 :(得分:0)

return new ArrayList<Contact>(new ArrayList<Contact>(contacts).subList(firstElement, lastElement));

注意:这将返回子列表独占 lastElement

注2:由于Kevin提到的原因,结果会被复制到另一个列表中。

答案 5 :(得分:0)

index.php?page=gallery