Alexander Mills
Alexander Mills

Reputation: 100060

Easily add element to varargs list

I have these signatures:

  public static <T, E> AsyncTask<List<T>, E> Parallel(AsyncTask<T,E> t, AsyncTask<T, E>... tasks) {
    return cb -> NeoParallel.Parallel(List.of(tasks), cb);
  }

  public static <T, E> AsyncTask<List<T>, E> Series(AsyncTask<T,E> t, AsyncTask<T, E>... tasks) {
    return cb -> NeoSeries.Series(List.of(tasks), cb);
  }

how can I easily add t to the List.of(tasks)?

This won't work because it creates an immutable list:

var listOfTasks = Arrays.asList(tasks);
listOfTasks.add(0, t);

is there a way to easily create a list that I can add to, or do it in one line?

Since this call is likely unperformant:

   listOfTasks.add(0, t);

I am looking for an alternative

Upvotes: 1

Views: 402

Answers (4)

whistling_marmot
whistling_marmot

Reputation: 3893

I'm late to the show, but you can use Guava Lists.

var listOfTasks = com.google.common.collect.Lists.asList(t, tasks);

Upvotes: 1

LppEdd
LppEdd

Reputation: 21134

While a short & performant (well maybe this isn't bad at all!) solution isn't possible with the current Java API, I'll showcase a one-liner with the help of Stream(s).

return cb -> NeoSeries.Series(concat(of(t), of(tasks)).collect(toList()), cb);

This line

concat(of(t), of(tasks)).collect(toList())

expanded becomes

Stream.concat(Stream.of(t), Stream.of(tasks))
      .collect(Collectors.toList());

This is lazily computed, and will avoid temporary state.


What the other answer fail to mention is null-handling. What if the varargs array is null? Arrays.asList would throw an Exception. The same for Stream.of

For that you can write a masking method such as

private static <T, E> AsyncTask<T, E>[] maskNull(final AsyncTask<T, E>[] tasks) {
    return tasks != null ? tasks : (AsyncTask<T, E>[]) new AsyncTask[0];
}

And use it like

of(maskNull(tasks))

Upvotes: 1

Alexander Mills
Alexander Mills

Reputation: 100060

So here is what I got:

before:

var tasks = Arrays.asList(args);
tasks.add(0,t);  // throws exception 

after:

var newList = new ArrayList<>(Arrays.asList(args));
newList.add(0,t);

the problem with the first one is it creates an immutable list that will throw an exception if you try to add to it after it's first created.

Upvotes: 0

David SN
David SN

Reputation: 3519

There is no concise way to create the list. Probably your best option is to create a new list, add both the array elements and the new element to the list and return a unmodifiable list using Collections.unmodifiableList.

    List<T> newList = new ArrayList<>(tasks.length + 1);
    newList.addAll(Arrays.asList(tasks));
    newList.add(t);
    List<T> unmodifiableList = Collections.unmodifiableList(newList);

Upvotes: 1

Related Questions