栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

是否可以在Java 8中创建由递归定义的无限增长的惰性方式集合?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

是否可以在Java 8中创建由递归定义的无限增长的惰性方式集合?

该解决方案将被创建为一个类,

FunctionalSequence
用于表示对象的惰性,无限序列,该对象序列由带整数参数的lambda函数定义。该函数可以迭代,也可以不迭代。对于迭代情况,
FunctionalSequence
该类将具有一种
initialize
用于设置起始值的方法。

这样的类的对象的声明将如下所示:

    FunctionalSequence<BigInteger> fiboSequence =  new FunctionalSequence<>();    fiboSequence.        initialize(Stream.of(BigInteger.ONE,BigInteger.ONE)).        setSequenceFunction( (i) -> fiboSequence.get(i-2).add(fiboSequence.get(i-1))        );

注意,就像问题中的递归lambda示例一样,我们无法声明该对象并在一个运算符中递归定义它。一个运算符用于声明,另一个运算符用于定义。

FunctionalSequence
类的定义:

import java.util.Iterator;import java.util.linkedList;import java.util.stream.Stream;public class FunctionalSequence<T> implements Iterable<T>{    linkedList<CountedFlighweight<T>> realList = new linkedList<>();    StackOverflowingFunction<Integer, T> calculate = null;    public FunctionalSequence<T> initialize(Stream<T> start){        start.forEachOrdered((T value) ->        {     realList.add(new CountedFlighweight<>());     realList.getLast().set(value);        });        return this;    }    public FunctionalSequence<T>  setSequenceFunction(StackOverflowingFunction<Integer, T> calculate){        this.calculate = calculate;        return this;    }    @Override    public Iterator<T> iterator() {        return new SequenceIterator();    }    public T get(int currentIndex) throws StackOverflowError{        if(currentIndex < 0) return null;        while (currentIndex >= realList.size()){ realList.add(new CountedFlighweight<T>());        }        try { return (T) realList.get(currentIndex).get(calculate, currentIndex);        } catch (Exception e) { return null;        }    }    public class SequenceIterator implements Iterator<T>{        int currentIndex;        @Override        public boolean hasNext() { return true;        }        @Override        public T next() { T result = null; if (currentIndex == realList.size()){     realList.add(new CountedFlighweight<T>()); } // here the StackOverflowError catching is a pure formality, by next() we would never cause StackOverflow try {     result = realList.get(currentIndex).get(calculate, currentIndex); } catch (StackOverflowError e) { } currentIndex++; return result;        }    }        public class CountedFlighweight<U>{        private boolean known = false;        private U reference;                private void set(U value){ reference = value; known = true;        }                public U get(StackOverflowingFunction<Integer, U> calculate, int index) throws StackOverflowError{ if (! known){     if(calculate == null) {         reference = null;     } else {         try {  reference = calculate.apply(index);         } catch (Exception e) {  reference = null;         }     } } known = true; return reference;        }    }    @FunctionalInterface    public interface StackOverflowingFunction <K, U> {        public U apply(K index) throws StackOverflowError;    }}

由于递归函数很容易遇到StackOverflowError,因此我们应该组织递归,以便在这种情况下,整个递归序列将回滚而不会真正满足任何更改,并引发异常。

FunctionalSequence的用法如下所示:

    // by iterator:    int index=0;    Iterator<BigInteger> iterator = fiboSequence.iterator();     while(index++<10){        System.out.println(iterator.next());    }

或者:

static private void tryFibo(FunctionalSequence<BigInteger> fiboSequence, int i){    long startTime = System.nanoTime();    long endTime;    try {        fiboSequence.get(i);        endTime = System.nanoTime();        System.out.println("repeated timing for f("+i+")=" + (endTime-startTime)/1000000.+" ns");    } catch (StackOverflowError e) {        endTime = System.nanoTime();        //e.printStackTrace();        System.out.println("failed counting f("+i+"), time=" + (endTime-startTime)/1000000.+" ns");    }       }

可以按以下方式使用最后一个功能:

    tryFibo(fiboSequence, 1100);    tryFibo(fiboSequence, 100);    tryFibo(fiboSequence, 100);    tryFibo(fiboSequence, 200);    tryFibo(fiboSequence, 1100);    tryFibo(fiboSequence, 2100);    tryFibo(fiboSequence, 2100);    tryFibo(fiboSequence, 1100);    tryFibo(fiboSequence, 100);    tryFibo(fiboSequence, 100);    tryFibo(fiboSequence, 200);    tryFibo(fiboSequence, 1100);

结果如下(出于测试需要,堆栈限制为256K):

11235813213455failed counting f(1100), time=3.555689 nsrepeated timing for f(100)=0.213156 nsrepeated timing for f(100)=0.002444 nsrepeated timing for f(200)=0.266933 nsrepeated timing for f(1100)=5.457956 nsrepeated timing for f(2100)=3.016445 nsrepeated timing for f(2100)=0.001467 nsrepeated timing for f(1100)=0.005378 nsrepeated timing for f(100)=0.002934 nsrepeated timing for f(100)=0.002445 nsrepeated timing for f(200)=0.002445 nsrepeated timing for f(1100)=0.003911 ns

看,对相同索引重复调用f(i)几乎不需要时间-
无需进行迭代。由于StackOverflowError,我们无法一次达到f(1100)。但是一旦我们达到f(200),f(1100)就可以达到了。我们做到了!



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/509292.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号