我有一个int数组。我需要为其每个元素添加 1。向每个元素添加给定常量的最短、最通用的方法是什么,即没有显式循环?我在网上查看并不断获取有关将元素添加到数组(即连接)的页面。
难道没有比遍历每个元素并添加常数更优雅的东西了吗?有某种标准库方法吗?
就此而言,如何在没有显式循环的情况下将两个数组相加(即矩阵相加)?
以下是如何使用Functional Java编写上述两种情况。
1.每个元素加1:
它是一个函数式编程库,因此它不提供变异操作。但是您可以轻松地自己添加它们。
public static <A> void transform(Array<A> xs, F<A, A> f) {
for(int i = 0; i < xs.length(); i++) {
xs.set(i, f.f(xs.get(i)));
}
}
利用:
transform(yourArray, Integers.add.f(1));
2.添加两个矩阵:
设xss
和yss
为两个矩阵,均为 类型Array<Array<Integer>>
。然后你可以添加它们:
xss.zip(yss).map(new F<P2<Array<Integer>, Array<Integer>>, Array<Integer>>() {
public Array<Integer> f(P2<Array<Integer>, Array<Integer>> p) {
Array<Integer> xs = p._1();
Array<Integer> ys = p._2();
return xs.zip(ys).map(new F<P2<Integer, Integer>, Integer>() {
public Integer f(P2<Integer, Integer> q) {
return q._1() + q._2();
}
});
}
});
这可能感觉比必要的更冗长,这是因为 Java 还不支持 lambda 表达式。同时,IDE 可以帮助使此类技术更易于使用。
如果一个不可修改的结果是可以的,并且你没有坚持使用数组,你可以使用一个可爱的技巧来延迟添加直到最后可能的时刻。但是一旦您需要访问整个结果数组,任何性能优势都会丢失,并且代码最终会变得比必要的更复杂。
public class OffsetArrayList extends AbstractList< Integer > {
private final List< Integer > liUnderlying;
private final int iOffset;
public OffsetArrayList( int iOffset, liUnderlying ) {
this.iOffset = iOffset;
this.liUnderlying = liUnderlying;
}
@Override
public Integer get( int iIndex ) {
return liUnderlying.get( iIndex ) + iOffset;
}
@Override
public Integer set( int iIndex, Integer iNewValue ) {
return liUnderlying.set( iIndex, iNewValue - iOffset ) + iOffset;
}
// etc.
}
// create new array
int[] aiInput = new int[] { 23, 98, -45 };
// two object allocations, but no new array created and no additions performed
OffsetArrayList alPlusOne = new OffsetArrayList( 1, Arrays.asList( aiInput ) );
// one addition performed; constant time
assert( alPlusOne.get( 0 ) == 24 );
// benefit murky, as we are adding to the same element repeatedly
for ( int i = 0; i < 1000000; ++i )
assert( alPlusOne.get( 2 ) == -44 );
// benefit lost, input destroyed
int[] aiOutput = alPlusOne.toArray( aiInput );