Java 8 turn on parallel() stream with boolean? [cl

2019-05-22 02:18发布

I am wondering how I could design methods that could either be run concurrently or single threaded. For example I have a method like this:

/**
 * Produces the norm of the two vector {@code v1}.
 * 
 * @param v1
 *            The first vector.
 * 
 * @param v2
 *            The second vector
 * 
 * @throws MathException
 *             Of type {@code DIMENSION_MISMATCH} if
 *             {@code v1.getDimension()} is != {@code v2.getDimension()}.
 */
public static Function<Vector, Double> norm = (v) -> {
    return Math.sqrt(
            IntStream.range(0, v.getDimension()).mapToDouble(i -> Math.pow(v.getEntry(i), 2)).sum());
};

And if I want to make the embedded stream parallel then I could create the same method over again and add parallel() to the stream but that adds a lot of boilerplate. Is there a parallel(boolean) switch that can be used?

3条回答
Evening l夕情丶
2楼-- · 2019-05-22 02:56

There is no switch like this in the API itself but you can add it yourself quite easily:

public static Function<Vector, Double> getNorm(boolean parallel) {
    return v -> {
        IntStream stream = IntStream.range(0, v.getDimension());
        stream = parallel ? stream.parallel() : stream;
        return Math.sqrt(stream.mapToDouble(i -> Math.pow(v.getEntry(i), 2)).sum());
    };
};

This code simply calls parallel() or not depending on the boolean parameter.

查看更多
我想做一个坏孩纸
3楼-- · 2019-05-22 03:03

Just wanted to post an example of what I think the API should look like in general to see what you think (I'm hoping Apache Commons Math will adopt this for 4.0, but the module will be available here meanwhile firefly-math-linear-real):

/**
 * Returns a {@link BiFunction} that multiplies the first vector {@code v1}
 * times the second vector {@code v2} .
 * 
 * Example {@code multiply().apply(v1, v2);}
 * 
 * @throws MathException
 *             Of type {@code DIMENSION_MISMATCH} if
 *             {@code v1.getDimension()} is != {@code v2.getDimension()}.
 */
public static BiFunction<Vector, Vector, Vector> multiply() {
    return VectorFunctions.multiply(false);
};

/**
 * Returns a {@link BiFunction} that multiplies the first vector {@code v1}
 * times the second vector {@code v2} .
 * 
 * Example {@code multiply(true).apply(v1, v2);}
 * 
 * @param parallel
 *            Whether to perform the multiplication in parallel.
 * 
 * @throws MathException
 *             Of type {@code DIMENSION_MISMATCH} if
 *             {@code v1.getDimension()} is != {@code v2.getDimension()}.
 */
public static BiFunction<Vector, Vector, Vector> multiply(boolean parallel) {
    return (v1, v2) -> {
        checkDimensionMismatch(v1, v2);
        IntStream stream = range(0, v1.getDimension());
        stream = parallel ? stream.parallel() : stream;
        return new Vector(stream.mapToDouble(i -> v1.getEntry(i)
                * v2.getEntry(i)).toArray());
    };
}

Thoughts?

Ole

查看更多
Emotional °昔
4楼-- · 2019-05-22 03:04

Create two functions

one named norm (implementation as provided in question), another named parallelNorm. You could reuse code between those functions.

Let encosing class controll parallelism

Your function norm resides in some class. I would

  • make function norm non-static
  • introduced final boolean member variable named parallel in encosing class
  • initialize parallel member variable in constructor
  • function norm would use parallel or non-parallel streams, based on value of parallel member variable

Use Decorator pattern to add parallelism

like in example above, I would use non-static function. I would make one class named Norm (with implementation of norm function like above). Then I would make class ParallelNorm extends Norm that would @Override norm function with parallel implementation

查看更多
登录 后发表回答