Короткий ответ
Если вы хотите «лучшую производительность», то более короткое время в итерации: используйте «для цикла» для маленькой матрицы, для больших случаев вы можете рассмотреть использование «параллельных потоков»
.. long answer
Я создал тест для измерения среднего времени выполнения одной из трех опций.
"Цикл For:"
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
doSomething(numOfVertices[i][j]);
}
}
"IntStream. диапазон: "
IntStream.range(0, size)
.forEach(i -> (IntStream.range(0, size))
.forEach(j -> {
doSomething(numOfVertices[i][j]);
}));
" Параллель IntStream.range: "
IntStream.range(0, size).parallel()
.forEach(i -> (IntStream.range(0, size))
.forEach(j -> {
doSomething(numOfVertices[i][j]);
}));
Этот раздел был удален, поскольку я не мог упростить его стоимость времени:
if (adjMatrix[i][j] != 0) {
graph.addEdge(i, j, adjMatrix[i][j]);
}
Ниже приведен весь тестовый код, который выполняет измерения для разных матриц. Каждый случай выполняется 10000 раз и дает среднее время. Вот результаты для запуска на моем компьютере. Для небольших матриц (от 1 х 1 до 100 х 100) для цикла это лучший вариант. Когда матрица большая (более 500 x 500), использование «IntStream.range parallel» выполняется быстрее. «IntStream.range» всегда хуже, чем «For loop» для каждого случая.
Size: 1
IntStream.range parallel: 0.002300
IntStream.range: 0.002200
For loop: 0.000000
Size: 5
IntStream.range parallel: 0.023000
IntStream.range: 0.000500
For loop: 0.000000
Size: 10
IntStream.range parallel: 0.025800
IntStream.range: 0.000300
For loop: 0.000100
Size: 50
IntStream.range parallel: 0.042200
IntStream.range: 0.004300
For loop: 0.000900
Size: 100
IntStream.range parallel: 0.035000
IntStream.range: 0.006000
For loop: 0.004300
Size: 500
IntStream.range parallel: 0.060200
IntStream.range: 0.102000
For loop: 0.079600
Size: 1000
IntStream.range parallel: 0.122000
IntStream.range: 0.379800
For loop: 0.347400
public static void main(String[] args) {
Arrays.asList(1, 5, 10, 50, 100, 500, 1000).forEach(
size -> {
System.out.println("Size: " + size);
Integer[][] numOfVertices = createArray(size);
Map<String, Runnable> toRun = Map.of(
"For loop:",
() -> {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
doSomething(numOfVertices[i][j]);
}
}
},
"IntStream.range:",
() -> {
IntStream.range(0, size)
.forEach(i -> (IntStream.range(0, size))
.forEach(j -> {
doSomething(numOfVertices[i][j]);
}));
},
"IntStream.range parallel:",
() -> {
IntStream.range(0, size).parallel()
.forEach(i -> (IntStream.range(0, size))
.forEach(j -> {
doSomething(numOfVertices[i][j]);
}));
}
);
int howManyTimes = 10000;
Map<String, Double> map = new HashMap<>();
toRun.entrySet().forEach(e -> {
double time = (((double)IntStream.range(0, howManyTimes).mapToObj(
(x) -> executionTime(e.getValue()))
.reduce(Long::sum).get()) / howManyTimes);
map.put(e.getKey(), time);
});
map.entrySet().forEach(e -> {
System.out.println(String.format("%25s %f", e.getKey(), e.getValue()));
});
}
);
}
private static Integer[][] createArray(int size) {
Integer[][] val = new Integer[size][size];
IntStream.range(0, size).forEach(
i -> IntStream.range(0,size).forEach(
j -> val[i][j] = (int)(Math.random() * 100)
)
);
return val;
}
private static int doSomething(int val) {
return val * val;
}
private static long executionTime(Runnable execThis)
{
long startTime = System.currentTimeMillis();
execThis.run();
long endTime = System.currentTimeMillis();
return (endTime-startTime);
}