如何优雅实现支持Float或Function参数的Stream专用Function返回方法?
优化动态值输入的Stream泛型实现方案
需求与问题
要实现一个返回Function的方法,用于Stream处理,方法的任意参数既可以是Float常量,也可以是Function<T, Float>动态计算逻辑,目的是简化创意编码中动态值的输入。但当前实现存在瓶颈:
- 用重载方法会产生大量重复代码
- 自定义
FObj类统一参数,需要为每个Float创建新实例,实现不够优雅
当前实现代码
class A{ Function<PVector, Float> range( Object scale, Object min, Object max ){ FObj<PVector> fScale = getFO( scale ); FObj<PVector> fMin = getFO( min ); FObj<PVector> fMax = getFO( max ); return pv -> map(noise(pv.x * fScale.getValue( pv ), pv.y * fScale.getValue( pv ) ), 0, 1, fMin.getValue( pv ), fMax.getValue( pv ) ); } <T> FObj<T> getFO ( Object input ) { if( input instanceof Float ) return new FObj<T>( (Float) input ); else if( input instanceof Function ) return new FObj<T>( (Function<T,Float>)input ); else throw new java.lang.RuntimeException("error"); } } class FObj<T>{ Function<T, Float> fn; float val; FObj( Function<T, Float> fn ){ this.fn = fn; } FObj( float val ){ this.val = val; } float getValue( T input ){ return fn != null ? fn.apply( input ) : val; } }
使用示例
A a; List<PVector> pvs = new ArrayList<>(); pvs.add( new PVector( 0, 0 ) ); Stream s = pvs.stream().map( a.range( 0.02f, 0f, 255f )::apply ); Stream s2 = pvs.stream().map( a.range( a.range( 0.02f, 0.1f, 0.002f ), 0f, 255f )::apply );
更优实现方案
方案1:用Function统一参数+静态工具方法包装常量
直接利用Java原生Function接口,把Float常量包装成始终返回该值的Function,避免自定义FObj类,同时保证类型安全。
class A { // 静态工具方法:将Float常量转为返回该值的Function public static <T> Function<T, Float> constant(Float value) { return t -> value; } // 核心方法:参数统一为Function,逻辑集中实现 public Function<PVector, Float> range(Function<PVector, Float> scaleFn, Function<PVector, Float> minFn, Function<PVector, Float> maxFn) { return pv -> { float scale = scaleFn.apply(pv); float noiseVal = noise(pv.x * scale, pv.y * scale); return map(noiseVal, 0, 1, minFn.apply(pv), maxFn.apply(pv)); }; } }
使用方式:
A a = new A(); List<PVector> pvs = new ArrayList<>(); pvs.add(new PVector(0, 0)); // 常量参数用constant包装 Stream<Float> s = pvs.stream().map(a.range(A.constant(0.02f), A.constant(0f), A.constant(255f))); // 嵌套调用直接传返回的Function,无需额外处理 Stream<Float> s2 = pvs.stream().map(a.range(a.range(A.constant(0.02f), A.constant(0.1f), A.constant(0.002f)), A.constant(0f), A.constant(255f)));
优势:
- 类型安全:编译期即可检查参数类型,避免运行时异常
- 减少冗余:去掉自定义
FObj类,复用Java原生接口 - 逻辑清晰:常量包装语义明确,嵌套调用自然支持
方案2:重载方法+核心逻辑复用
如果希望保留原有的简洁调用方式(直接传Float无需手动包装),可以通过重载方法实现,所有重载最终复用核心的range方法,避免重复代码。
class A { // 静态工具方法:将Float常量转为返回该值的Function private static <T> Function<T, Float> constant(Float value) { return t -> value; } // 核心方法:参数全为Function public Function<PVector, Float> range(Function<PVector, Float> scaleFn, Function<PVector, Float> minFn, Function<PVector, Float> maxFn) { return pv -> { float scale = scaleFn.apply(pv); float noiseVal = noise(pv.x * scale, pv.y * scale); return map(noiseVal, 0, 1, minFn.apply(pv), maxFn.apply(pv)); }; } // 重载1:scale为Float,其余为Function public Function<PVector, Float> range(Float scale, Function<PVector, Float> minFn, Function<PVector, Float> maxFn) { return range(constant(scale), minFn, maxFn); } // 重载2:min为Float,其余为Function public Function<PVector, Float> range(Function<PVector, Float> scaleFn, Float min, Function<PVector, Float> maxFn) { return range(scaleFn, constant(min), maxFn); } // 重载3:max为Float,其余为Function public Function<PVector, Float> range(Function<PVector, Float> scaleFn, Function<PVector, Float> minFn, Float max) { return range(scaleFn, minFn, constant(max)); } // 重载4:三个参数全为Float public Function<PVector, Float> range(Float scale, Float min, Float max) { return range(constant(scale), constant(min), constant(max)); } }
使用方式:
和原代码完全一致,无需修改调用逻辑:
A a = new A(); List<PVector> pvs = new ArrayList<>(); pvs.add(new PVector(0, 0)); Stream<Float> s = pvs.stream().map(a.range(0.02f, 0f, 255f)); Stream<Float> s2 = pvs.stream().map(a.range(a.range(0.02f, 0.1f, 0.002f), 0f, 255f));
优势:
- 调用简洁:保留原有的直观调用方式,用户无需学习新的API
- 无重复代码:所有重载方法都复用核心逻辑,维护成本低
- 类型安全:编译期确保参数类型合法,避免运行时错误
内容的提问来源于stack exchange,提问作者jakejake
相关产品推荐
相关产品推荐

