Alex Rivera | Logout

Java: "cons" an item to a list

Asked 2011-08-15T19:54:39.787
15

I have an Item which has a method List<Item> getChildren() (which returns an immutable list) and for each of the items I have, I need to create a list of the item followed by its children.

What's the quickest way to "cons" (in the Lisp/Scheme sense) my item to create a new immutable list? I can certainly do the following, but it seems wrong/wasteful:

public List<Item> getItemAndItsChildren(Item item)
{
    if (item.getChildren.isEmpty())
        return Collections.singletonList(item);
    else
    {
        // would rather just "return cons(item, item.getChildren())"
        // than do the following -- which, although straightforward,
        // seems wrong/wasteful.
        List<Item> items = new ArrayList<Item>();
        items.add(item);
        items.addAll(item.getChildren());
        return Collections.unmodifiableList(items);
    }
}
Edit
Report

3 Answers

2

You shouldn't need to special case an Item with no children.

public List<Item> getItemAndItsChildren(Item item)
{
    List<Item> items = new ArrayList<Item>();
    items.add(item);
    items.addAll(item.getChildren());
    return Collections.unmodifiableList(items);
}

Also, if you are looking to use a language that isn't verbose, then Java is a poor choice. I'm sure you can do what you like in far less code in Groovy and Scala which both run on the JVM. (Not to mention JRuby or Jython.)

answered 2011-08-15T20:04:46.817
2

It sounds like you're looking for something like a CompositeList, similar to the Apache Commons' CompositeCollection. An implementation could be as naive as this:

public class CompositeList<T> extends AbstractList<T>{
    private final List<T> first, second;

    public CompositeList(List<T> first, List<T> second) {
        this.second = second;
        this.first = first;
    }

    @Override
    public T get(int index) {
        if ( index < first.size() ) {
            return first.get(index);
        } else {
            return second.get(index - first.size());
        }
    }

    @Override
    public int size() {
        return first.size() + second.size();
    }
}

And you could use it like this:

public List<Item> getItemAndItsChildren(Item item)
{
    return Collections.unmodifiableList( 
        new CompositeList<Item>(Collections.singletonList(item), item.getChildren()) );
}

But there are huge caveats that make such a class difficult to use...the main problem being that the List interface cannot itself mandate that it is unmodifiable. If you are going to use something like this you must ensure that clients of this code never modify the children!

answered 2011-08-15T21:13:06.023
2

I use these. (using guava's ImmutableList and Iterables)

/** Returns a new ImmutableList with the given element added */
public static <T> ImmutableList<T> add(final Iterable<? extends T> list, final T elem) {
    return ImmutableList.copyOf(Iterables.concat(list, Collections.singleton(elem)));
}

/** Returns a new ImmutableList with the given elements added */
public static <T> ImmutableList<T> add(final Iterable<? extends T> list, final Iterable<? extends T> elems) {
    return ImmutableList.copyOf(Iterables.concat(list, elems));
}

/** Returns a new ImmutableList with the given element inserted at the given index */
public static <T> ImmutableList<T> add(final List<? extends T> list, final int index, final T elem) {
    return ImmutableList.copyOf(Iterables.concat(list.subList(0, index), Collections.singleton(elem), list.subList(index, list.size())));
}

/** Returns a new ImmutableList with the given element inserted at the given index */
public static <T> ImmutableList<T> add(final List<? extends T> list, final int index, final Iterable<?extends T> elems) {
    return ImmutableList.copyOf(Iterables.concat(list.subList(0, index), elems, list.subList(index, list.size())));
}

But none of them are efficient.

Example of prepending/consing an item to a list:

ImmutableList<String> letters = ImmutableList.of("a", "b", "c");
add(letters, 0, "d");

For more efficient immutable/persistent collections you should, as @eneveu points out, look at pcollections, although I have no idea what the quality of that library is.

answered 2011-08-16T08:54:59.570

Your Answer