Skip to content
Advertisement

List view of concatenated lists

I want to create a list view that consists of the concatenation of a number of other lists.

Example:

List<Integer> l1 = Lists.newArrayList(1);
List<Integer> l2 = Lists.newArrayList(2);
List<Integer> l3 = Lists.newArrayList(3);

// This call should not copy any of the argument lists content
List<Integer> concatenation = new ConcatenationListView(l1, l2, l3);

System.out.println(concatenation); // Prints [1, 2, 3]
l3.add(4);
System.out.println(concatenation); // Prints [1, 2, 3, 4]

What kind of technique and or pattern can I use in Java to fulfill these requirements?

Details

  • I want the concatenation to be lazy. (That’s the meaning of “view” in this context.)
  • I want change to the component lists the reflect on the concatenation. (Also the meaning of “view”).
  • The view need not to be modifiable.
  • This is kind of the opposite of the List.subList method.
  • It is similar to what the Guava Iterables.concat method do, but I need a list as the result, not an iterable.
  • My question is similar to this one, but I need a List as the resulting concatenation, where the poster of the other question is content with an Iterable as the result.

Edit: Solution

I posted a complete solution based on Sergey’s answer.

Advertisement

Answer

Java class library does not have a composition class like that, so you would need to code it yourself.

Since you want the class to allow modifications to underlying lists, you wouldn’t get better efficiency than O(L), where L is the number of lists managed by the view, because index translation would require you to walk the list of lists each time you need to read or insert at a specific index.

On the other hand, this makes implementation very straightforward – the code that translates the index would look as follows:

class ListView : List<T> {
    private List<List<T>> lists = ...
    public T get(int index) {
        int i = 0;
        while (i != lists.size() && index > lists.get(i).size()) {
            index -= lists.get(i++).size();
        }
        if (i == lists.size()) {
            throw new IndexOutOfBoundsException();
        }
        return lists.get(i).get(index);
    }
    ...
}
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement