-1

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.

Csaba Toth
  • 10,021
  • 5
  • 75
  • 121
  • None of the answers are the same in the supposed duplicate Question cited above. There are some variations, but not the same. – Csaba Toth May 13 '20 at 21:41

1 Answers1

1

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.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • Oh, I'm refactoring this right now constantly, and although it's named list, it's actually an array right now: `private ARObject[] arObjectList = {`. The reason is that `CompletableFuture.allOf(` simply unpacks the array into a series of arguments (that's what it expects). I'd be happy to convert it back to a list. All I want is a simple way to extract the list of Futures from the series of POJOs, and then pass that to `CompletableFuture.allOf` or another way to wait until all futures are finished. – Csaba Toth Apr 12 '20 at 01:26
  • I can omit the explicit cast from the toArray expression: `CompletableFuture[] texturePromises = Stream.of(arObjectList).map(ARObject::getTexture).toArray(CompletableFuture[]::new);`. I agree that it's still ugly, so if there's something better I'm happy to refactor. – Csaba Toth Apr 12 '20 at 01:28