I made a pagination algorithm but in my opinion it is too complicated and it is quite difficult to be understood. This algorithm should show 5 pages where in the middle is the current page. It should also show two pages before and two pages after the selected page (if these pages exist).
So, I just want to generate the array which is underlined in the above picture.
Here is my code:
public class Pagination {
private int totalPages;
private int selectedPage;
private int offset;
public Pagination() {
totalPages = 6;
selectedPage = 4;
offset = 5;
}
public static void main(String[] args) {
Pagination pagination = new Pagination();
System.out.println(pagination.buildPaginationConditions().toString());
}
private List<Integer> buildPaginationConditions() {
if (selectedPage <= offset / 2) {
return doShowFirstPages();
}
return buildPagination();
}
private List<Integer> doShowFirstPages() {
List<Integer> pagination = new LinkedList<Integer>();
for (int i = 1; i <= offset; i++) {
if (totalPages >= i) {
pagination.add(i);
}
}
return pagination;
}
private List<Integer> buildPagination() {
List<Integer> pagination = new LinkedList<Integer>();
int delta = offset / 2; // How many pages to left/right
int paginationMiddle = (int) Math.ceil((double) offset / 2);
for (int i = 1; i <= offset; i++) {
if (i < paginationMiddle) {
pagination.add(selectedPage - delta);
delta--;
continue;
}
if (paginationMiddle == i) {
pagination.add(selectedPage);
delta = 1;
continue;
}
if (totalPages >= selectedPage + delta) {
pagination.add(selectedPage + delta);
delta++;
continue;
}
if (selectedPage >= totalPages - 1) {
//If it is the last or the penultimate page shift the pages to the right woth 1/2 positions
int noOfGapsInPagination = offset - pagination.size();
int temp = new Integer(offset);
for (int j = 0; j < noOfGapsInPagination; j++) {
pagination.add(j, totalPages - (--temp));
}
break;
}
}
return pagination;
}
}
The algorithm works but I want to write that for loop
from buildPagination()
much more simpler because it looks too complicated now .
I know that I can to extract those pices of code from if conditions
in smaller methods but it is not going to simplify the code to much. Do you have any suggestions?
-
\$\begingroup\$ I tried to understand the algorithm but didn't sucseed. Please add more examples, especially the edge cases. \$\endgroup\$shanif– shanif2020年04月10日 08:26:13 +00:00Commented Apr 10, 2020 at 8:26
-
\$\begingroup\$ I think the solution should be calculating the start and the end of the range. But it is very different from your solution. Am I missing something? \$\endgroup\$shanif– shanif2020年04月10日 08:32:25 +00:00Commented Apr 10, 2020 at 8:32
1 Answer 1
the most simple algorithm would be to calculate the start and end indices
// set start index relative to selected
int start = selectedPage - (offset / 2);
// adjust for first pages
start = Math.max(start, 1);
// set end index relative to start
int end = start + offset - 1;
// adjust start and end for last pages
if (end > totalPages) {
end = totalPages;
start = end - offset + 1;
}
return IntStream.rangeClosed(start, end).boxed()
.collect(Collectors.toList());
as for code review:
- method signatures correctly return interface
List
. however, there are two places where you initialize the list with a concrete implementation. now imagine you would decide thatArrayList
is better suited. you need to remember to modify two places. - while on the subject: don't use
LinkedList
. it has an extremely narrow use case where it is preferable overArrayList
. this is not one of them. Especially if you initialize theArrayList
with initial size. - use Java 8 collection stream (if you've learned it) it is more efficient and concise than for loop
- The code does not use java standard indentation. code inside if block should be indented inward.
-
\$\begingroup\$ Pff, it is much more simpler and it works perfectly. Thank you very much for the advices. \$\endgroup\$John R.– John R.2020年04月10日 10:39:21 +00:00Commented Apr 10, 2020 at 10:39