我有一个包裹在一个对象中的1D数组列表,我想用java-8流在1个单独的数组中收集它们并收集。
给出具有
数组的类Itemclass A{
int x;
}
class Item{
A[] parts=new A[];
public A[] getParts(){
return parts;
}
}
所以如果我有清单l
List<Item> l=new ArrayList<>();
l.add(new Item());
l.add(new Item());
我需要在一个A类型的单个数组中收集这两个对象中的内容。
因此,如果第一个项目有parts={1,2}
和第二个项目parts={3,4}
,那么输出应该是某种方式
A[] out={1,2,3,4}
我试着做
l.stream().map(Item::getParts).collect(Collectors.toList()).toArray(new A[n]);
但显然它有很多问题。
答案 0 :(得分:2)
将每个Item
映射到其A[]
数组。然后,当有一个A[]
流只是平面映射时,它将获得每个数组的每个A
,并在最后生成一个数组。
A[] array = l.stream().map(x -> x.getParts())
.flatMap(x -> Arrays.stream(x))
.toArray(A[]::new); // [1, 2, 3, 4]
但是,如果您只对int
值感兴趣,那么还有一个额外的步骤
int[] array = l.stream().map(x -> x.getParts())
.flatMap(x -> Arrays.stream(x))
.mapToInt(x -> x.getX())
.toArray();
答案 1 :(得分:1)
您想使用.flatMap()
代替.map()
;在lambda中只生成数组中新项目的流。
答案 2 :(得分:1)
请尝试以下操作:
static void test() {
List<Item> l = new ArrayList<>();
l.add(new Item(1, 2,5));
l.add(new Item(3, 4,10));
System.out.println(l);
int totalNoOfParts = l.stream().mapToInt(item->item.getParts().length).reduce(0, Integer::sum);
A[] allParts = l.stream().map(item -> item.getParts()).collect(() -> new A[totalNoOfParts],
(c, e) -> System.arraycopy(e, 0, c, getNextPos(c), e.length),
(c1, c2) -> System.arraycopy(c2, 0, c1, getNextPos(c1), c2.length));
System.out.println(Arrays.asList(allParts));
}
static int getNextPos(A[] a) {
for (int i = 0; i < a.length; i++) {
if (a[i] == null)
return i;
}
throw new InvalidParameterException("Invalid index value");
}
我修改了你的Item类,使其具有固定长度的数组。
class Item {
A[] parts = new A[3];
Item(int... values) {
Objects.requireNonNull(values, "Argument Not Valid");
for (int i = 0; i < values.length; i++) {
parts[i] = new A();
parts[i].x = values[i];
}
}
public A[] getParts() {
return parts;
}
}