Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: "cons" an item to a list

Tags:

java

list

guava

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);
    }
}
like image 511
Jason S Avatar asked Aug 15 '11 19:08

Jason S


People also ask

Can you append to a list in Java?

There are two methods to add elements to the list. add(E e): appends the element at the end of the list. Since List supports Generics, the type of elements that can be added is determined when the list is created. add(int index, E element): inserts the element at the given index.

How do you check if an object is present in a list in Java?

contains() method can be used to check if a Java ArrayList contains a given item or not. This method has a single parameter i.e. the item whose presence in the ArrayList is tested. Also it returns true if the item is present in the ArrayList and false if the item is not present.

How do you check if an object contains a string Java?

The Java String contains() method is used to check whether the specific set of characters are part of the given string or not. It returns a boolean value true if the specified characters are substring of a given string and returns false otherwise.


2 Answers

I'd change my requirements. In most cases, you don't need a List in your interface, an Iterable will do nicely. Here's the method:

public Iterable<Item> getItemWithChildren(Item item)    {
    return Iterables.unmodifiableIterable(
        Iterables.concat(
            Collections.singleton(item),
            item.getChildren()
        )
    );
}

and here's the shortened version (with static imports):

return unmodifiableIterable(concat(singleton(item), item.getChildren()));
like image 57
Sean Patrick Floyd Avatar answered Sep 21 '22 03:09

Sean Patrick Floyd


The ability to create a new immutable list by concatenating a head element to a tail that may be shared between other lists requires a singly-linked list implementation. Java doesn't provide anything like this out of the box, so your ArrayList solution is as good as anything.

It's also going to be relatively efficient, assuming that these lists are short-lived and you don't have tens of thousands of element in the list. If you do, and if this operation is taking a significant portion of your execution time, then implmenting your own single-linked list might be worthwhile.

My one change to improve your existing efficiency: construct the new list with a capacity (1 + size of old list).

like image 22
parsifal Avatar answered Sep 19 '22 03:09

parsifal