我试图弄清楚如何使用Streams API来实现一个zip函数,该函数将无限数量的int []作为参数;从每个元素中取出第i个元素;把它们放在一个元组中(显然需要一个自定义元组对象 - 我有)并返回一个元组列表(即List)。
基本上,对于:
[ Tuple(1, 4), Tuple(2, 5), Tuple(3, 6) ]
建议的方法应该返回:
java.util.List<Tuple>
/**
* Return a list of tuples, where each tuple contains the i-th element
* from each of the argument sequences. The returned list is
* truncated in length to the length of the shortest argument sequence.
*
* @param args the array of ints to be wrapped in {@link Tuple}s
* @return a list of tuples
*/
public static List<Tuple> zip(int[]... args) {
List<Tuple> retVal = new ArrayList<>();
// Find the array with the minimum size
int minLength = Arrays.stream(args).map(i -> new Integer(i.length)).min((a, b) -> a.compareTo(b)).get();
for(int i = 0;i < minLength;i++) {
Tuple.Builder builder = Tuple.builder();
for(int[] ia : args) {
builder.add(ia[i]);
}
retVal.add(builder.build());
}
return retVal;
}
这是一个功能,可以完成我在&#34;正常&#34;中所做的事情。方式:
SubClass
答案 0 :(得分:4)
解决方案是在索引上创建Stream,并使用mapToObj
将每个int
映射到Tuple
。此外,由于您已经拥有Builder
个对象,我们可以利用它来收集元素。
假设我们添加一个方法Tuple.Builder.addAll(Tuple.Builder other)
,其目的是将一个构建器添加到另一个构建器,我们可以使用以下代码:
public static List<Tuple> zip(int[]... args) {
// Find the array with the minimum size
int minLength = Arrays.stream(args).mapToInt(i -> i.length).min().orElse(0);
return IntStream.range(0, minLength)
.mapToObj(i ->
Arrays.stream(args)
.mapToInt(ia -> ia[i])
.collect(Tuple::builder, Tuple.Builder::add, Tuple.Builder::addAll)
.build()
).collect(Collectors.toList());
}
(如果您不想支持并行执行,则可以使用(b1, b2) -> { throw new IllegalStateException(); }
抛出异常而不添加addAll
方法。)
作为旁注,可以简化用于查找最小数组大小的代码:您不需要插入Integer
,您可以将每个数组映射到其长度并获取至少min()
。这将返回OptionalInt
;如果Stream为空,它可能会抛出异常而不是获取它的值,而是使用orElse(0)
,这样,在空的Stream的情况下,返回一个空列表。