我传递了一个对象集合(在我的例子中是一些 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;
}
你可以使用 Guava 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)
是一个更简单的实现。
如果你可以要求数据分页为
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
。
如果您希望元素有明确的顺序,则应该使用
List
,而不是 collection
。 List
和 Collection
之间的基本区别在于 List
的元素具有固定的顺序。它还定义了非常方便的方法subList(int start, int end)
,它创建一个子列表,它是原始列表的别名,仅包含您想要的元素,而无需将它们复制到新列表的开销。
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));
}
return new ArrayList<Contact>(new ArrayList<Contact>(contacts).subList(firstElement, lastElement));
注意:这将返回子列表exclusivelastElement
注2:由于Kevin提到的原因,结果被复制到另一个列表。
Iterables.partition(contacts, pageSize).forEachRemaining(paginatedContacts->{/*Operation here*/});