2
\$\begingroup\$

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).

enter image description here

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?

\$\endgroup\$
2
  • \$\begingroup\$ I tried to understand the algorithm but didn't sucseed. Please add more examples, especially the edge cases. \$\endgroup\$
    – shanif
    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
    Apr 10, 2020 at 8:32

1 Answer 1

2
\$\begingroup\$

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:

  1. 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 that ArrayList is better suited. you need to remember to modify two places.
  2. while on the subject: don't use LinkedList. it has an extremely narrow use case where it is preferable over ArrayList. this is not one of them. Especially if you initialize the ArrayList with initial size.
  3. use Java 8 collection stream (if you've learned it) it is more efficient and concise than for loop
  4. The code does not use java standard indentation. code inside if block should be indented inward.
\$\endgroup\$
1
  • \$\begingroup\$ Pff, it is much more simpler and it works perfectly. Thank you very much for the advices. \$\endgroup\$
    – John R.
    Apr 10, 2020 at 10:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.