Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6203867
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 24, 20262026-05-24T04:59:26+00:00 2026-05-24T04:59:26+00:00

As a pet project I’m trying to implement an immutable list data structure in

  • 0

As a pet project I’m trying to implement an immutable list data structure in Java while minimizing copies as much as possible; I know about Google Collections but this is not what I’m after since list manipulations just return new copies of the old list.

I have come up with two different approaches to the problem; both are based on doubly linked lists, like this:

[head: element1] <--> [element2] <--> [tail: element3]

So every list consists of the tuple {head, tail}.


First, let’s examine the simple case of appending or prepending an element to list A, resulting in list B:

A:                 [head: element1] <--> [element2] <--> [tail: element3]
B: [head: element0] <--> [element1] <--> [element2] <--> [tail: element3]

This is O(1). Since iterating over the list happens between head and tail only, A won’t know anything about the new element prepended or appended to B.

It gets interesting when we try to insert or remove an arbitrary element in the list.

Indexed elements approach

Every list has a unique sequential id starting from 0. Every element has an array of {prev, next} pointers corresponding to the list ids:

  [element1] <--> [element2] <--> [element3] <--> [element4]
A:   [0] <---------> [0] <---------> [0] <---------> [0]
B:   [0] <---------> [1] <-------------------------> [1]
C:   ...

So when removing element3 from list A with id = 0, the prev or next pointers, respectively, with id = 1 (list B) of element2 and element4 are altered to reflect the result of the requested operation; element1 remains unaltered. When iterating over a list with index x, in order to obtain the correct prev or next pointers, max(elementIdCount, x) is used to compute the correct index (which would be 0 for element1 and 1 for element2 if we are iterating over B with id = 1, for example).

Adding or replacing elements is done in the same way. This is also O(1), except when the element id arrays need to be resized, which should happen relatively infrequently.

The big problem with this is of course garbage collection – once an element has been added to a list, it is never going to be released until ALL references to modified versions of the original list are released. This could be kind of remedied by making a copy of the whole list on every 10 modifications for example.

This kind of list is especially well suited to code constructs like this:

while (...)
    list = list.addElement(...);

since only one reference to the list is held at any given time.

Iterator approach

The other approach is abusing iterators in order to make the resulting list look like the expected modified version; so each modified immutable list holds a reference to its “source” list and an additional tuple {operation, element, position}, like this:

A: [head: element1] <--> [element2] <--> [tail: element3]
B: source: A, {add, element_to_add, 1}

B‘s iterator then calls its source list iterator (in this case A‘s) except when it encounters the element that has been modified (added, removed or replaced), in which case it returns that element and then continues again with the source iterator.

The obvious disadvantage here is that the nested iterator depth grows with every modified version of a list. This means that making a raw copy every now and then is necessary as well.

Does anybody have any suggestions on how this may be improved? Also, any pointers to any data structures invented in the 60s that may be useful are more than welcome 🙂

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-24T04:59:26+00:00Added an answer on May 24, 2026 at 4:59 am

    You can create a head::tail like list, and get the benefits of easy creation and good memory footprint, and then provide an API that layers a skip list on top to get efficient random access when needed.

    As far as efficient mutation in middle, the skip list view might have a side table mapping mutated indices to elements, and a binary searchable array mapping original index to index offsets after inserts and removes.

    All this mapping raises the question of how to provide efficient immutable maps for some definition of efficient. The best way I’ve come up with is to use b trees which allow for O(log n) access to sortable keys, and O(log n) node creation on insertion and removal. The number of nodes shared between two holders of a b-tree based map after k modifications are approx. (n – k log n) which is pretty good in practice for infrequently updated maps.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm using CodeMirror along with jQuery to provide syntax highlighting on a pet PoC
I know the pet object below is stored to session by using @SessionAttributes, but
This is mostly a pet peeve of mine, but it annoys me to no
XML element I am accessing: is here, if below sample is unreadable: http://api.petfinder.com/pet.find?&animal=dog&count=150&location=90605&key=a94884c2349b5b6975ec84fb51ac3ec4 <pets>
Possible Duplicate: Default class inheritance access I know I can set the protection level
I have 2 drop down list, one is college and other is branch, so
I want to learn a new programming language. I have in mind stuff like
I have an existing domain at work and haven't been able to limit the
Is it too long? When I fill it out and click submit, nothing happens.

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.