老实说,我会保留传统的嵌套循环,在我看来,这是一种更简洁的方法。流并不能替代所有“旧”Java 代码。尽管如此,我还是发布了一些可能的方法。
第一种方法
这是第一种可能的方法(面向对象)。创建一个类ArrayElement
保存指数:
class ArrayElement<V> {
public final int row;
public final int col;
public final V elem;
...
}
然后,您需要创建一种方法,该方法从单个数组(我们将调用的数组)创建元素流flatMap
), and 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);
}
最后主要看起来像这样:
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);
和输出:
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]
此解决方案的缺点是它为数组中的每个对象创建一个新对象。
第二种方法
第二种方法更直接,它的想法相同,但您不会为数组中的每个 elem 创建一个新的 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);
}
}
它输出:
0, 0, One, false
0, 1, Two, false
1, 0, null, true
1, 1, Four, false
第三种方法
使用两个实例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));
});
产生与上面相同的输出。
我的结论
使用 Streams 是可行的,但我真的更喜欢用例中的嵌套循环,因为您需要 x 和 y 值。