gpt4 book ai didi

java - 如何在获得可比性能的同时在 Java8 中进行 monadicaly 编程?

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:57:02 25 4
gpt4 key购买 nike

Java 8 中的 monadic 编程是否更慢?下面是我的测试(使用右偏 Either 为每个计算创建新实例)。命令式版本快 1000 倍。如何在获得可比性能的同时在 Java8 中进行 monadicaly 编程?

主.java

public class Main {

public static void main(String args[]){
Main m = new Main();
m.work();
m.work2();
}


public void work(){
final long start = System.nanoTime();
final Either<Throwable,Integer> result =
Try(this::getInput).flatMap((s) ->
Try(this::getInput).flatMap((s2) ->
parseInt(s).flatMap((i) ->
parseInt(s2).map((i2) ->
i + i2
))));
final long end = System.nanoTime();
result.map(this::println).leftMap(this::println);
System.out.println((end-start)/1000+"us to execute");
}

public void work2(){
Object result;
final long start = System.nanoTime();
try {
final String s = getInput();
final String s2 = getInput();

final int i = parzeInt(s);
final int i2 = parzeInt(s2);
result = i + i2;
}catch(Throwable t){
result=t;
}
final long end = System.nanoTime();
println(result);
System.out.println((end-start)/1000+"us to execute");
}

public <A> A println(final A a){
System.out.println(a);
return a;
}

public String getInput(){
final Integer value = new Random().nextInt();
if(value % 2 == 0) return "Surprise!!!";
return value+"";
}

public Either<Throwable,Integer> parseInt(final String s){
try{
return Either.right(Integer.parseInt(s));
}catch(final Throwable t){
return Either.left(t);
}
}

public Integer parzeInt(final String s){
return Integer.parseInt(s);
}
}

Either.java

public abstract class Either<L,R>
{
public static <L,R> Either<L,R> left(final L l){
return new Left(l);
}

public static <L,R> Either<L,R> right(final R r){
return new Right(r);
}

public static<L,R> Either<L,R> toEither(final Optional<R> oR,final L l){
return oR.isPresent() ? right(oR.get()) : left(l);
}

public static <R> Either<Throwable,R> Try(final Supplier<R> sr){
try{
return right(sr.get());
}catch(Throwable t){
return left(t);
}
}

public abstract <R2> Either<L,R2> flatMap(final Function<R,Either<L,R2>> f);

public abstract <R2> Either<L,R2> map(final Function<R,R2> f);

public abstract <L2> Either<L2,R> leftMap(final Function<L,L2> f);

public abstract Either<R,L> swap();

public static class Left<L,R> extends Either<L,R> {
final L l;

private Left(final L l){
this.l=l;
}

public <R2> Either<L,R2> flatMap(final Function<R,Either<L,R2>> f){
return (Either<L,R2>)this;
}

public <R2> Either<L,R2> map(final Function<R,R2> f){
return (Either<L,R2>)this;
}

public <L2> Either<L2,R> leftMap(final Function<L,L2> f){
return new Left(f.apply(l));
}

public Either<R,L> swap(){
return new Right(l);
}
}

public static class Right<L,R> extends Either<L,R> {
final R r;

private Right(final R r){
this.r=r;
}

public <R2> Either<L,R2> flatMap(final Function<R,Either<L,R2>> f){
return f.apply(r);
}

public <R2> Either<L,R2> map(final Function<R,R2> f){
return new Right(f.apply(r));
}

public <L2> Either<L2,R> leftMap(final Function<L,L2> f){
return (Either<L2,R>)this;
}

public Either<R,L> swap(){
return new Left(r);
}
}
}

最佳答案

虽然我不太理解你的努力——显然你正在使用 map 来产生副作用,而且你真的没有任何替代方法来从 Either 类型中拆箱结果——我已经测量过你在 JMH 上的工作是这样的。您对 Random 的用法有误,我已更正。这是我使用的代码:

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@OperationsPerInvocation(Measure.SIZE)
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@State(Scope.Thread)
@Fork(1)
public class Measure
{
static final int SIZE = 1;

@Benchmark public Either<Throwable, Integer> workMonadically() {
final Either<Throwable,Integer> result =
Try(this::getInput).flatMap((s) ->
Try(this::getInput).flatMap((s2) ->
parseInt(s).flatMap((i) ->
parseInt(s2).map((i2) ->
i + i2
))));
return result;
}

@Benchmark public Object workImperatively() {
Object result;
try {
final String s = getInput();
final String s2 = getInput();

final int i = parzeInt(s);
final int i2 = parzeInt(s2);
result = i + i2;
}catch(Throwable t){
result=t;
}
return result;
}

public String getInput() {
final Integer value = ThreadLocalRandom.current().nextInt();
if (value % 2 == 0) return "Surprise!!!";
return String.valueOf(value);
}

public Either<Throwable,Integer> parseInt(final String s){
try{
return Either.right(Integer.parseInt(s));
}catch(final Throwable t){
return Either.left(t);
}
}

public Integer parzeInt(final String s){
return Integer.parseInt(s);
}

public static abstract class Either<L,R>
{
public static <L,R> Either<L,R> left(final L l){
return new Left<>(l);
}

public static <L,R> Either<L,R> right(final R r){
return new Right<>(r);
}

public static<L,R> Either<L,R> toEither(final Optional<R> oR,final L l){
return oR.isPresent() ? right(oR.get()) : left(l);
}

public static <R> Either<Throwable,R> Try(final Supplier<R> sr){
try{
return right(sr.get());
}catch(Throwable t){
return left(t);
}
}

public abstract <R2> Either<L,R2> flatMap(final Function<R,Either<L,R2>> f);

public abstract <R2> Either<L,R2> map(final Function<R,R2> f);

public abstract <L2> Either<L2,R> leftMap(final Function<L,L2> f);

public abstract Either<R,L> swap();

public static class Left<L,R> extends Either<L,R> {
final L l;

private Left(final L l){
this.l=l;
}

@Override public <R2> Either<L,R2> flatMap(final Function<R,Either<L,R2>> f){
return (Either<L,R2>)this;
}

@Override public <R2> Either<L,R2> map(final Function<R,R2> f){
return (Either<L,R2>)this;
}

@Override public <L2> Either<L2,R> leftMap(final Function<L,L2> f){
return new Left<>(f.apply(l));
}

@Override public Either<R,L> swap(){
return new Right<>(l);
}
}

public static class Right<L,R> extends Either<L,R> {
final R r;

private Right(final R r){
this.r=r;
}

@Override public <R2> Either<L,R2> flatMap(final Function<R,Either<L,R2>> f){
return f.apply(r);
}

@Override public <R2> Either<L,R2> map(final Function<R,R2> f){
return new Right<>(f.apply(r));
}

@Override public <L2> Either<L2,R> leftMap(final Function<L,L2> f){
return (Either<L2,R>)this;
}

@Override public Either<R,L> swap(){
return new Left<>(r);
}
}
}
}

这是结果:

Benchmark                 Mode  Cnt     Score     Error  Units
Measure.workImperatively avgt 5 1646,874 ± 137,326 ns/op
Measure.workMonadically avgt 5 1990,668 ± 281,646 ns/op

所以几乎没有区别。

关于java - 如何在获得可比性能的同时在 Java8 中进行 monadicaly 编程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29019165/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com