我是Java 8的Lambda表达式的新手,我想制定以下内容:我有一个二维数组,我想在我的应用程序代码中迭代几次,并对数组中的项进行处理.在我做以下之前:
public static abstract class BlaBlaIterator {
private final BlaBla[][] blabla;
public BlaBlaIterator(final BlaBla[][] blabla) {
this.blabla = blabla;
}
public void iterate() {
final int size = blabla.length;
for (int x = 0; x < size; x++) {
for (int y = 0; y < size; y++) {
final BlaBla bla = blabla[x][y];
iterateAction(x, y, bla, bla == null);
}
}
}
public abstract void iterateAction(int x, int y, BlaBla bla, boolean isNull);
}
Run Code Online (Sandbox Code Playgroud)
然后
BlaBla[][] blabla = ...
new BlaBlaIterator(blabla) {
@Override
public void iterateAction(final int x, final int y, final BlaBla bla, final boolean isNull) {
//...
}
}.iterate();
Run Code Online (Sandbox Code Playgroud)
至关重要的是:我需要访问当前的x/y,我需要计算像isNull这样的东西.
我现在要做的是将其转换为lambda.我想写这样的东西:
BlaBla[] blabla = ...
blabla.stream().forEach((x, y, blabla, isNull) -> ... );
Run Code Online (Sandbox Code Playgroud)
要从二维数组中获取流,我可以做到
Arrays.stream(field).flatMap(x -> Arrays.stream(x))
Run Code Online (Sandbox Code Playgroud)
但后来我松开了x/y信息,无法传递像isNull这样的计算内容.我怎样才能做到这一点?
说实话,我会保留传统的嵌套循环,IMO这是一个更清洁的方法.Streams不是所有"旧"Java代码的替代品.不过,我发布了一些可能的方法.
这是第一种可能的方法(面向对象).创建一个类ArrayElement来保存索引:
class ArrayElement<V> {
public final int row;
public final int col;
public final V elem;
...
}
Run Code Online (Sandbox Code Playgroud)
然后,您需要创建一个方法,从单个数组(我们将要调用的数组)创建元素流flatMap,然后iterateAction打印出当前实例
private static <T> Stream<ArrayElement<T>> createStream(int row, T[] arr) {
OfInt columns = IntStream.range(0, arr.length).iterator();
return Arrays.stream(arr).map(elem -> new ArrayElement<>(row, columns.nextInt(), elem));
}
private static <V> void iterateAction(ArrayElement<V> elem) {
System.out.println(elem);
}
Run Code Online (Sandbox Code Playgroud)
最后主要看起来像这样:
String[][] arr = {{"One", "Two"}, {"Three", "Four"}};
OfInt rows = IntStream.range(0, arr.length).iterator();
Arrays.stream(arr)
.flatMap(subArr -> createStream(rows.nextInt(), subArr))
.forEach(Main::iterateAction);
Run Code Online (Sandbox Code Playgroud)
和输出:
ArrayElement [row=0, col=0, elem=One]
ArrayElement [row=0, col=1, elem=Two]
ArrayElement [row=1, col=0, elem=Three]
ArrayElement [row=1, col=1, elem=Four]
Run Code Online (Sandbox Code Playgroud)
此解决方案的缺点是它为数组中的每个Object创建一个新Object.
第二种方法更直接,它是相同的想法,但你不为数组中的每个元素创建一个新的ArrayElement实例.再一次,这可以在一个衬里完成,但lamdba会变得丑陋,所以我将它们分解为方法(如第一种方法):
public class Main {
public static void main(String[] args) {
String[][] arr = { {"One", "Two"}, {null, "Four"}};
OfInt rows = IntStream.range(0, arr.length).iterator();
Arrays.stream(arr).forEach(subArr -> iterate(subArr, rows.nextInt()));
}
static <T> void iterate(T[] arr, int row) {
OfInt columns = IntStream.range(0, arr.length).iterator();
Arrays.stream(arr).forEach(elem -> iterateAction(row, columns.nextInt(), elem, elem == null));
}
static <T> void iterateAction(int x, int y, T elem, boolean isNull) {
System.out.println(x+", "+y+", "+elem+", "+isNull);
}
}
Run Code Online (Sandbox Code Playgroud)
它输出:
0, 0, One, false
0, 1, Two, false
1, 0, null, true
1, 1, Four, false
Run Code Online (Sandbox Code Playgroud)
使用两个实例 AtomicInteger
String[][] arr = {{"One", "Two"}, {null, "Four"}};
AtomicInteger rows = new AtomicInteger();
Arrays.stream(arr).forEach(subArr -> {
int row = rows.getAndIncrement();
AtomicInteger colums = new AtomicInteger();
Arrays.stream(subArr).forEach(e -> iterateAction(row, colums.getAndIncrement(), e, e == null));
});
Run Code Online (Sandbox Code Playgroud)
它产生与上面相同的输出.
它可以使用Streams,但我更喜欢你的用例中的嵌套循环,因为你需要x和y值.
| 归档时间: |
|
| 查看次数: |
6539 次 |
| 最近记录: |