Convert Stream<Stream<T>> to T[][] with Streams/Lambda's in Java

JavaJd :

I am looking to see if there was a better way to solve my dilemma having to use these signatures (note: the T[][] is required because of Spock testing and I am providing T[][] as a data provider)

My method signature is:

public <T> T[][] createArrays(Class<T> clazz, T...items)

I am using a static method which has the signature:

public static <T> Stream<Stream<T>> of(T...items)

and calculates all of the permutations of the passed array.

My solution, retyped by hand so forgive typos, is:

public static <T> T[][] createArrays(Class<T> clazz, T...items){
  Stream<Stream<T>> streams = EnumPerm.of(items);
  List<List<T>> lists = streams.map(s -> ).collect(toList()).collect(toList());
  T[][] outer = (T[][])(Array.newInstance(clazz,lists.size(),items.length);
  for(int x=0;x<lists.size();x++){
    List<T> innerList = lists.get(x);
    for(int y=0;y<items.length;y++){
      outer[x][y] = innerList.get(x);
    }      
  }

  return outer;
}

I attempted .map(s -> s.toArray(....)) but could not get T[] cast to work, the IntFunction generator to work, nor use the Array.newInstance to work. I likely am missing something and would greatly appreciate any suggestions.

Take care and thank you for your time in advance!!

Holger :

You can use Array.newInstance like this:

public static <T> T[][] createArrays(Class<T> clazz, T... items) {
    Stream<Stream<T>> streams = EnumPerm.of(items);
    return streams
        .map(s -> s.toArray(len -> (T[])Array.newInstance(clazz, len)))
        .toArray(len -> (T[][])Array.newInstance(items.getClass(), len));
}

without any intermediate Lists.

There is a variant for creating arrays of the same type without unchecked casts, like this

public static <T> T[][] createArrays(Class<T> clazz, T... items) {
    Stream<Stream<T>> streams = EnumPerm.of(items);
    T[] template = Arrays.copyOf(items, 0);
    return streams
        .map(s -> s.toArray(len -> Arrays.copyOf(template, len)))
        .toArray(len -> (T[][])Array.newInstance(template.getClass(), len));
}

but since there is no existing array of type T[][], we can’t avoid Array.newInstance for creating the outer array. But note that is doesn’t need the clazz parameter.

If you want to enforce the use of the specified clazz parameter for all arrays, you can use

public static <T> T[][] createArrays(Class<T> clazz, T... items) {
    Stream<Stream<T>> streams = EnumPerm.of(items);
    return streams
        .map(s -> s.toArray(len -> (T[])Array.newInstance(clazz, len)))
        .toArray(len -> (T[][])Array.newInstance(clazz, len, 0));
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=77919&siteId=1