如何使用Java流合并和排列数组



以下代码按预期工作:

private static void experiment() {
final UUID[] uuids = new UUID[]{null, UUID.randomUUID()};
final String[] names = new String[]{null, "", " ", "t", "someName"};
final String[] descrs = new String[]{null, "", " ", "t", "someDescr"};
final List<Arguments> allArguments = new ArrayList<>();
Arrays.stream(uuids)
.forEach(uuid -> Arrays.stream(names)
.forEach(name -> Arrays.stream(descrs)
.forEach(descr -> allArguments
.add(Arguments.of(uuid, name, descr)))));
}

allArguments最终包含以下内容(准编码(,由50个元素组成:

{
{null, null, null},
{null, null, ""},
...
{68dc3afc-a13e-405f-a761-12169e73ecf6, "someName", "someDescr"}
}

然而,我想要两个改变:

  1. 我想要源值的n数组,而不是硬编码的三个数组(uuid、name、descr(
  2. 我想通过以下方式使用来解决问题:
final Collection<Arguments> allArguments = 
<whatever>
<whatever>
...
.collect(<whatever>);

有人能给这个问题提个建议吗?

试试这个。

static Function<List<Object>, Stream<List<Object>>> add(Object[] a) {
return list -> Arrays.stream(a).map(y -> {
List<Object> n = new ArrayList<>(list);
n.add(y);
return n;
});
}

static void experiment() {
UUID[] a = {null, UUID.randomUUID()};
String[] b = {null, "b"};
Integer[] c = {100, 200};
String[] d = {"X", "Y"};
List<List<Object>> s = Stream.of(Arrays.asList())
.flatMap(add(a))
.flatMap(add(b))
.flatMap(add(c))
.flatMap(add(d))
.collect(Collectors.toList());
for (List<Object> e : s)
System.out.println(e);
}

输出:

[null, null, 100, X]
[null, null, 100, Y]
[null, null, 200, X]
[null, null, 200, Y]
[null, b, 100, X]
[null, b, 100, Y]
[null, b, 200, X]
[null, b, 200, Y]
[0c52b3ab-18b2-460e-ac1d-152db85a603d, null, 100, X]
[0c52b3ab-18b2-460e-ac1d-152db85a603d, null, 100, Y]
[0c52b3ab-18b2-460e-ac1d-152db85a603d, null, 200, X]
[0c52b3ab-18b2-460e-ac1d-152db85a603d, null, 200, Y]
[0c52b3ab-18b2-460e-ac1d-152db85a603d, b, 100, X]
[0c52b3ab-18b2-460e-ac1d-152db85a603d, b, 100, Y]
[0c52b3ab-18b2-460e-ac1d-152db85a603d, b, 200, X]
[0c52b3ab-18b2-460e-ac1d-152db85a603d, b, 200, Y]

或者你也可以这样做。

static List<List<Object>> cartesianProduct(Object[]... arrays) {
return Arrays.stream(arrays)
.map(a -> add(a))
.reduce(Stream.of(Arrays.asList()),
(s, p) -> s.flatMap(p), (a, b) -> Stream.concat(a, b))
.collect(Collectors.toList());
}

UUID[] a = {null, UUID.randomUUID()};
String[] b = {null, "b"};
Integer[] c = {100, 200};
String[] d = {"X", "Y"};
for (List<Object> list : cartesianProduct(a, b, c, d))
System.out.println(list);

使用streams,您可以首先将每个数组表示为2d数组(假设数组的长度相同(,并获得2d数组的然后将该流reduce表示为单个2d阵列

在线试用!

public static void main(String[] args) {
String[] uuids = {null, "", "68dc3afc", "112b1030"};
String[] names = {null, "", "someName", "anotherName"};
String[] descrs = {null, "", "someDesrc", "anotherDesrc"};
String[][] arr2d = mergeAndPermute(uuids, names, descrs);
// output
Arrays.stream(arr2d).map(Arrays::toString).forEach(System.out::println);
//[null, null, null]
//[, , ]
//[68dc3afc, someName, someDesrc]
//[112b1030, anotherName, anotherDesrc]
}
public static String[][] mergeAndPermute(String[]... arrays) {
// assume that the lengths of the arrays are the same
return Arrays
// Stream<String[]>
.stream(arrays)
// represent each array as a 2d array
// Stream<String[][]>
.map(arr -> Arrays.stream(arr)
.map(str -> new String[]{str})
.toArray(String[][]::new))
// reduce a stream of 2d arrays to a single 2d array
// by sequentially concatenating rows of 2d arrays
.reduce((arr2d1, arr2d2) -> IntStream
// iterate over the indexes of 2d arrays
.range(0, arr2d1.length)
// concatenate rows of 2d arrays
.mapToObj(i -> Stream
.concat(Arrays.stream(arr2d1[i]),
Arrays.stream(arr2d2[i]))
.toArray(String[]::new))
// return a single 2d array
.toArray(String[][]::new))
.orElse(null);
}

另请参阅:
•将列表地图转换为地图列表
•将2d阵列中每列的所有元素相加

最新更新