You now have a header and trailer pseudo-node:

header <--> first <--> second <--> ... <--> last <--> trailer

Instead, you would have to connect the first and last in both directions.

        .-> first  <--> second <--> ... <--> last <-.
        |                                           |
        '-------------------------------------------'

Alternatively, you could also merge header and trailer in one node, but this then is no "pure" circularly linked list, since you have to step over the header/trailer node on traversal.

        .-> first  <--> second <--> ... <--> last <--> header/trailer <-.
        |                                                               |
        '---------------------------------------------------------------'
Answer from Paŭlo Ebermann on Stack Overflow
🌐
DEV Community
dev.to › nk_sk_6f24fdd730188b284bf › mastering-linked-lists-in-java-doubly-and-circular-linked-lists-5hcd
Mastering Linked Lists in Java: Doubly and Circular Linked Lists - DEV Community
September 23, 2025 - Doubly Linked List (DLL) Circular ... to the previous node · A pointer to the next node · This allows traversal in both forward and backward directions....
🌐
Sanfoundry
sanfoundry.com › java-program-implement-circular-doubly-linked-list
Java Program to Implement Circular Doubly Linked List - Sanfoundry
May 23, 2022 - insert at begining 2. insert at end 3. insert at position 4. delete at position 5. check empty 6. get size 1 Enter integer element to insert 5 Circular Doubly Linked List = 5 <-> 5 Do you want to continue (Type y or n) y Circular Doubly Linked List Operations 1. insert at begining 2. insert at end 3. insert at position 4. delete at position 5. check empty 6. get size 1 Enter integer element to insert 7 Circular Doubly Linked List = 7 <-> 5 <-> 7 Do you want to continue (Type y or n) y Circular Doubly Linked List Operations 1. insert at begining 2. insert at end 3. insert at position 4. delete
People also ask

What are the advantages of using a Circular Doubly Linked List?
Advantages include efficient insertion and deletion operations, bidirectional traversal support, constant time access to both ends of the list, and suitability for representing cyclic data structures.
🌐
akcoding.com
akcoding.com › home › data structures tutorial : a comprehensive guide › linear data structures › circular doubly linked list
Introduction to Circular Doubly Linked List 5 key concept
Are Circular Doubly Linked Lists thread-safe?
Circular Doubly Linked Lists are not inherently thread-safe. Synchronization mechanisms may need to be implemented to ensure thread safety in concurrent environments.
🌐
akcoding.com
akcoding.com › home › data structures tutorial : a comprehensive guide › linear data structures › circular doubly linked list
Introduction to Circular Doubly Linked List 5 key concept
🌐
Software Testing Help
softwaretestinghelp.com › home › java › doubly linked list in java – implementation & code examples
Doubly Linked List In Java – Implementation & Code Examples
April 1, 2025 - The circular doubly linked list is more complex and they form a circular pattern with the previous pointer of the first node pointing to the last node and the next pointer of the last node pointing to the first node.
🌐
Javatpoint
javatpoint.com › circular-doubly-linked-list
Circular Doubly Linked List - javatpoint
Circular Doubly Linked List with Introduction, Asymptotic Analysis, Array, Pointer, Structure, Singly Linked List, Doubly Linked List, Circular Linked List, Binary Search, Linear Search, Sorting, Bucket Sort, Comb Sort, Shell Sort, Heap Sort, Merge Sort, Selection Sort, Counting Sort, Stack, Qene, Circular Quene, Graph, Tree, B Tree, B+ Tree, Avl Tree etc.
🌐
Skillsoft
skillsoft.com › home › data structures & algorithms in java: doubly & circular linked lists
Data Structures & Algorithms in Java: Doubly & Circular Linked Lists - Java - INTERMEDIATE - Skillsoft
This means additional space is required to store each node, but it also makes certain operations faster, such as traversing backwards over the elements in the linked list. You'll also learn about the circular linked list, where the tail of the linked list points back to the head of the linked list.
🌐
GitHub
github.com › contactsunny › Circular_Double_LinkedList_Implementation_Java_POC
GitHub - contactsunny/Circular_Double_LinkedList_Implementation_Java_POC: This is a simple example of a circular double linked list implementation in Java. · GitHub
This is a simple example of a circular double linked list implementation in Java. We create a custom Node class which can take values of generic type T, so that we can create linked lists of different types using the same implementation class.
Author: contactsunny
Find elsewhere
🌐
Contactsunny
blog.contactsunny.com › home › tech
Circular Double Linked List Implementation in Java | The ContactSunny Blog
January 16, 2020 - We’ll continue our data structures journey with this post about how to implement a circular Double Linked List (DLL) in Java. This is very similar to the standard DLL with the only difference being the connection of the head with the tail. That ...
🌐
Medium
medium.com › @chetanshingare2991 › mastering-linked-lists-doubly-circular-and-doubly-circular-implementations-in-kotlin-16e77a7ecaa3
Mastering Linked Lists: Doubly, Circular, and Doubly Circular Implementations in Kotlin | by chetan shingare | Medium
January 18, 2025 - Doubly Circular Linked List: Android: Implementing a carousel view, managing a circular buffer with bidirectional navigation. Real Life: Managing a ring buffer, implementing a circular playlist with forward and backward navigation.
🌐
AK Coding
akcoding.com › home › data structures tutorial : a comprehensive guide › linear data structures › circular doubly linked list
Introduction to Circular Doubly Linked List 5 key concept
April 26, 2024 - Here’s how you can perform traversal operations in a Circular Doubly Linked List: Start from any node in the list. Move to the next node using the “next” pointer until you reach the starting point again. Print or process the data in each node during traversal. Start from any node in the list. Move to the previous node using the “prev” pointer until you reach the starting point again. Print or process the data in each node during traversal. Here’s a Java implementation of traversal operations in a Circular Doubly Linked List:
🌐
Stack Overflow
stackoverflow.com › questions › 66147460 › question-about-conceptual-understanding-for-circular-doubly-linked-list-in-java
intellij idea - Question about Conceptual Understanding for Circular doubly linked list in Java - Stack Overflow
An empty list should have no node. ... Yes. i have made my instance of Doublenode Pointer to Null; as it has nothing, an empty circular linkedlist. ... Maybe the "Standard implementation"(jdk8) can guide you/offer valueable insights. (Or "drill down" (with your IDE) into java.util.LinkedList;)
Top answer
1 of 5
5

Error handling

I would expect the following to:

  • Write errors to System.err rather than System.out.
  • Better yet, throw a java.lang.IllegalArgumentException that can be handled accordingly by the caller.

Aside from someone watching the output, they'd have no way to know a call to remove failed. There certainly wouldn't be any (convenient, idiomatic) way for the program to know it had failed.

    public void remove(int index) {
        int counter = 1;
        int currentSize = size();

        if (index > currentSize + 1 || index <= 0) {
            System.out.println("Invalid index.");
            return;
        }

Throwing an exception also simplifies, because the return is no longer necessary.

Indexing

You also seem to be indexing starting at 1 rather than 0. This is inconsistent with pretty much any other indexed data structure in Java or most other modern, mainstream programming language.

Iteration

Many operations (like printing a string representation) on your list your become easier if you implement an iterator over lists.

2 of 5
7

I think it is unfortunate that insert and remove call size. While I understand that you would want to reject a bad index early in the function, calling size gives these functions the property that inserting/removing cost time linear in the size of the list, not linear in the index as may be expected (or hoped for). The out-of-range-ness could be detected during the (inevitable) iteration up to the insertion/removal index.

Generally data structures and algorithms should not print errors to System.out (where it may be mixed awkwardly in the middle of other output, or be invisible in GUI applications, etc, anyway it's a mixing of concerns), but report them to the caller.

🌐
GeeksforGeeks
geeksforgeeks.org › dsa › introduction-to-circular-doubly-linked-list
Introduction to Circular Doubly Linked List - GeeksforGeeks
July 23, 2025 - A circular doubly linked list is defined as a circular linked list in which each node has two links connecting it to the previous node and the next node.
🌐
Medium
medium.com › code-writers › understanding-doubly-circular-linked-lists-with-source-code-in-c-java-283ef30dc1c1
Understanding Doubly Circular Linked Lists (With Source Code in C++ & JAVA) | by Sushmita Singh | Code Writers | Medium
April 4, 2023 - Insertion at the beginning of the list ∘ #2. Insertion at the end of the list ∘ #3. Insertion in between the nodes · Deletion ∘ #1. Deletion from the beginning ∘ #2. Deletion from the end ∘ #3. Deletion of a specific node · Advantages of Doubly Circular Linked List ·
🌐
Dartmouth College
cs.dartmouth.edu › ~scot › cs10 › lectures › 6 › 6.html
Circular, doubly linked lists with a sentinel
If you took CS 1, then you know that the simplest, cleanest way to implement a linked list is with a circular, doubly linked list with a sentinel. The implementation is in SentinelDLL.java.
🌐
Coderanch
coderanch.com › t › 646020 › java › method-Circular-Doubly-Linked-List
Need help with method for Circular Doubly Linked List (Beginning Java forum at Coderanch)
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums · this forum made possible by our volunteer staff, including ... ... For the program I have to create, I need to be able to work with the elements of a circular doubly linked list to do the following: Find an element in the list (specified as an argument) Insert an element after a specified element (specified as an argument) Delete an element (specified as an argument) Display the elements in the list I can insert elements and display the elements, but I can't figure out how to search for an element, insert an element after a specified element, or delete an element.
Top answer
1 of 3
10

Java style convention

One of the first thing you should do when working in a new language is to look at style convention. You used C++ convention and not the Java one. Class name should be PascalCase and method name should be camelCase. Unless it's a constant, you should not use _ (except in some precise case).

    if(isEmpty()) {
        ...
    }
    else {
        ...
    }

Should be :

    if(isEmpty()) {
        ...
    } else {
        ...
    }

The else should be on the same line that the last }.

Variable declaration

I always like to start the class with class and instance variables. It will let me know what my class is using. So private node<T> head; should be before the constructor.

I would suggest that you avoid using single letters as a variable name. Reading x and p does not help to know what it's used for. Try to use descriptive name, there is no or almost no length limitation, so be creative!

Documentation

I see that you have good comments for your public methods. I would suggest that you use JavaDoc. It will almost change nothing, just some syntax changes. Here is one example of a JavaDoc :

/**
 * Here is the description of what the method is doing. Some specific things that will      
 * be helpful to the caller like {@link OtherClass#methodName()}
 * @param aParam What your param is or used for in your method
 * @return what your method is returning
 * @see OtherClass
 */

As @tot2 pointed in comments, you can use tools that will generate html from your Javadoc. If you check the Java 7 html documentation, it's all been built with it. It's useful if you use an IDE as it can be easily accessible when you code. In Eclipse, if you put your mouse hover a method/class, it will show you the Javadoc in a well presented way. If you want more information I would suggest you visit this Oracle page.

Bracket

This is a personal choice, but I would suggest to always use brackets even if you only have one line and it's possible to omit brackets.

if(isEmpty()) return;
else if(p == p.getNext()) {
    System.out.println(p.getKey());
}
if(isEmpty()) {
  return;
} else if(p == p.getNext()) {
    System.out.println(p.getKey());
}

This will "save" you time if you need to add a new line of code in the if part. It will also prevent so weird bug if someone try to add a line, but forget that there was no brackets.

2 of 3
6

While Marc-Andre already talked a lot about Java Style Conventions, here's my 2 cents on your implementation.

Inheriting:

You did create a List. In Java it's customary to implement Interfaces if you have classes with similar use-cases and methods.

public class list<T> {

This should/could be:

public class List<T> implements java.util.List<T> {

In fact

Naming:

I suggest you change the name of your implementation to avoid confustion. Java already comes with two lists ((interface)java.util.List and (class)java.awt.List), that are just named List, you don't really need to introduce a third one ;)

By the way, if you implement an interface you are required to Override the methods that are specified by it.

In the case of List that's quite a few, including but not restricted to:

public int size();
public boolean isEmpty();
public boolean contains(T item);
public void add(T item);
public void remove(T item);

When implementing them make sure to use the @Override annotation:

@Override
public void add(T item) {
    Node<T> oldHead = this.head;
    this.head = new Node<T>(item);
    head.setNext(oldHead);
    oldHead.setPrev(head);
    size++;
}

Which brings me to my next point:

Hiding inner classes:

There is absolutely no need to show how your list works internally by exposing a node-class to all who got your List.

Instead in Java you can use a feature called 'Inner Classes'. It's quite simple:

public class MyList<T> implements List<T> {
    private Node<T> head = null;
    private int size = 0; //you could also use long when you expect more than 2150kk items

    public MyList() {}

    private static class Node<T> {
        private final T value;
        private Node<T> next = null;
        private Node<T> prev = null;

        protected Node<T>(T value) {
            this.key = value;
        }

        T value() {
            return this.value;
        }

        void setNext(Node<T> newNext) {
            this.next = newNext;
        }

        void setPrev(Node<T> newPrev) {
            this.prev = newPrev;
        }

        Node<T> getNext() {
            return this.next;
        }

        Node<T> getPrev() {
            return this.prev;
        }
    }
    //Here goes the rest of MyList implementation
}

I am using a few tricks here:
The first thing you might probably notice is the keyword final. In case you haven't heard of it yet: The compiler enforces, that a final variable is only assigned once. This allows me to make an Instance of Node single-use only. If you want to change an item, you will have to replace it with a whole new node.

Beware this does not prevent changes to Objects themselves. It is very possible to do:

private final Map<String, String> demonstration = new HashMap<String, String>();

public void doSomething() {
    demonstration.put("Demo", "Value");
}

The other thing is that I initialize next and previous not in the constructor. This is just my personal preference!

Additionally the inner class is static. This prevents access from the inner class to the outer one when using this. For more information have a look at this CR-Answer.

While we're at constructors / initialization:

Consistency:

One big issue I see with your code, is that you don't work consistently:

public Node() {
    this.setNext(null);
    this.setPrev(null);
}

public List() {
    head = null;
}

You use quite the mix here. In the Node constructor you use the setters - even with this keyword - to instantiate your Node, in your list you do it directly - and without this - on the field.

While both may be legal, I personally prefer using the middle way. As you have seen in the code above I usually initialize fields by using the this, but not the setter methods. In case of equal names it's required to use this so I usually put it everywhere.


Example no. 2:

node<T> f = head, b = head.getPrev();

node<T> b = head.getPrev();
b.getPrev().setNext(head);

here you have some statements on one and the same line, while throughout the rest of your code, you mostly place statements on separate lines.

Here I advise to wherever possible use the second approach. One Statement has one line and one line has one (or no) statement.

🌐
W3Schools
w3schools.com › dsa › dsa_data_linkedlists_types.php
DSA Linked Lists Types
Lines 13 and 22: These links makes the doubly linked list circular.