Search code examples
javajava-streamtoarray

How to convert toArray result to a CompletableFuture<Texture>[] type?


I looked through dozens of answers, but most they do is advice string::new or similar tricks. In my case the type I want to convert is CompletableFuture<Texture>. Here is this POJO:

class ARObject {
  CompletableFuture<Texture> texture;

  void setTexture(CompletableFuture<Texture> texture) {
    Log.d(TAG, String.format("Texture set for %d", resourceId));
    this.texture = texture;
  }

  CompletableFuture<Texture> getTexture() {
    return texture;
  }
}

Due to refactorings arObjectList is right now an array.

private ARObject[] arObjectList = {
    ...
};

(Obviously this is a simplification, the object has many more fields). All I want is to obtain an array of CompletableFuture<Texture> so I can pass that to CompletableFuture.allOf(...). Here is what I want:

CompletableFuture<Texture>[] texturePromises = Stream.of(arObjectList).map(ARObject::getTexture).toArray();
CompletableFuture.allOf(texturePromises)

But toArray returns am Object[] according to the IDE. CompletableFuture<Texture>::new generator didn't work but it wouldn't be a good idea anyway, we dont' want to reallocate or mess with those futures. Just return the array of them. Passing new CompletableFuture<Texture>[arObjectList.length] doesn't compile.

Do not mark this question as duplicate unless you are absolutely sure and can point out a solution. I read through more than a dozen entries.


Solution

  • Is arObjectList a list? Then it's obviously arObjectList.size(); not arObjectlist.length.

    In general, mixing generics and arrays doesn't work. Consider arrays, especially arrays of non-primitives, obsolete. 'Pain' (in the sense that you have to jump through hoops, possibly dipping into 'raw types' which causes warnings) ensues if you try to mix the two.

    In general you cannot make arrays with generics in them; it's a limitation. What you can do is make an array of a raw type and cast it.

    Object o = new List<String>[10]; // illegal
    List<String>[] o = (List<String>[]) new List[10]; // legal, but warnings
    

    thus, something like:

    CompletableFuture<Texture>[] texturePromises = (CompletableFuture<Texture>[]) Stream.of(arObjectList).map(ARObject::getTexture).toArray(CompletableFuture[]::new);

    will do the job. With warnings. The warnings cannot be avoided; the real solution is to stop using arrays for mostly everything; certainly stop using them here.