破坏式更新和函数式更新的比较
- 现在我们需要取旅行,我们要坐火车,所以不可避免的要倒火车,下面的类是一个简单的单项列表的结构
public class Train {
//0火车票价格
private int price;
//火车站点
private Train onward;
public Train(int price, Train onward) {
this.price = price;
this.onward = onward;
}
//setter getter
}
- 现在我们从北京->广州,玩够了之后,我们启程广州->上海,我们现在写一个方法,将两段路程连接起来
public void test() {
Train train1 = new Train(12, null);
Train train2 = new Train(14, null);
Train link = link(train1, train2);
System.out.println(link); // Train{price=12, onward=Train{price=14, onward=null}}
System.out.println(train1); // Train{price=12, onward=Train{price=14, onward=null}}
System.out.println(train2); // Train{price=14, onward=null}
}
public static Train link(Train train1 , Train train2){
if (null == train1) return train2;
Train t = train1;
// 如果他又下一个,那么就遍历到没有下一个元素为止
while (t.getOnward() != null){
t = t.getOnward();
}
t.setOnward(train2);
return t;
}
- 我们发现,上面的这种方式有个相当大的缺点,那么就是他改变了传入的train1的结构,本来我们想的只是连接两个trian对象,返回一个连接好的对象,而现在却造成了train也跟着变动了
- 采用函数式编程的方案如下
public void test() {
Train train1 = new Train(12, null);
Train train2 = new Train(14, null);
Train link = link(train1, train2);
System.out.println(link); // Train{price=12, onward=Train{price=14, onward=null}}
System.out.println(train1); // Train{price=14, onward=null}
System.out.println(train2); // Train{price=14, onward=null}
}
public static Train link(Train train1 , Train train2){
return train1 == null ? train2 : new Train(train1.getPrice(),link(train1.getOnward(),train2));
}
- 上面是一个队规调用,如果你不熟悉递归,那么可以参考这一篇文章:递归学习
- 上面的输出结果也证明了,我们并没有对原来的Train做修改,但是这需要注意的是,我们并没有创建整个新的Train的副本,而是创建train2之前的所有对象的副本,而train2或者之后的元素都是共享的原来的train2,如图