Reputation: 311
I started learning Java 8 features, streams and lambdas in particular, and I'm quite confused. I tried to rewrite the piece of code below
MyClass graph = new MyClass(V);
for (int i = 0; i < numOfVertices; i++) {
for (int j = 0; j < numOfVertices; j++) {
if (adjMatrix[i][j] != 0) {
graph.addEdge(i, j, adjMatrix[i][j]);
}
}
}
I wrote this:
int b = IntStream.range(0, numOfVertices - 1).parallel()
.map(i -> (IntStream.range(0, numOfVertices - 1))
.map(j -> {
if (adjMatrix[i][j] != 0) {
graph.addEdge(i, j, adjMatrix[i][j]);
}
}));
Of course it doesn't work. What would be the proper way to rewrite the code above? I'm also looking for the best performance, so I attempted to use the parallel method.
Thanks!
Upvotes: 0
Views: 1418
Reputation: 4120
If you want "best performance", the shorter time in iteration: Use "for loop" for small matrix, for bigger cases you can consider use "parallel streams"
I created a test to measure the average time of execution one of three options.
"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]);
}));
This section was removed as I could not simpulate it's time cost:
if (adjMatrix[i][j] != 0) {
graph.addEdge(i, j, adjMatrix[i][j]);
}
Below is the whole test code that perform measurement for different matrix. It runs every case 10000 times and gives the average time. Here are the results for run on my computer. For small matrix (form 1 x 1 to 100 x 100) for loop is the best option. When matrix is big (more than 500 x 500) using "IntStream.range parallel" is faster. "IntStream.range" is always worse than "For loop" for every case.
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);
}
Upvotes: 0
Reputation: 1647
Regardless to performance this is a simple form rewriting it with stream:
IntStream.range(0, numOfVertices - 1)
.forEach(i -> IntStream.range(0, numOfVertices - 1)
.filter(j -> adjMatrix[i][j] != 0)
.forEach(j -> graph.addEdge(i, j, adjMatrix[i][j])));
Upvotes: 1